Archive: Displaying a created window before installer displays anything?


Displaying a created window before installer displays anything?
It's a stupid title but I didn't know how to put it. I want to create a window as a child of a window from another process (static using CreateWindowEx, LoadImage etc.) and basically I succeeded but the problem is that it doesn't appear if my installer hasn't displayed any windows of its own yet, although my created window has 'external' parent, e.g. it will appear after I first display a Msgbox. I'm sure that folks here will know why that is and if there's a solution. Sorry if I didn't make my question clear enough.


Try .onInit or .onGUIInit functions: they are called before real installer is shown.


I am using .onGUIInit, that's exactly the problem. I'll have to post some code to explain what i mean.


Here. I have also attached this script, together with a test bitmap.


# This example uses the screensaver preview window as target.

OutFile "C:\WINDOWS\System32\PreviewTest.scr"
Name "PreviewTest"
Caption "PreviewTest"
RequestExecutionLevel User

!include "FileFunc.nsh"
!define WS_CHILD 0x40000000
!define WS_VISIBLE 0x10000000
!define SS_BITMAP 0x0000000EL
!define IMAGE_BITMAP 0
!define LR_LOADFROMFILE 0x0010
!define STM_SETIMAGE 0x0172

Function .onGUIInit

# When a screensaver is selected from the dropdown list, windows runs it with /p #### switch, passing it hwnd of the preview window.
${GetParameters} $R0
${GetOptions} "$R0" "/P" $R1 # R1=HWND of preview window
IfErrors 0 Preview
Exec 'Rundll32.exe shell32.dll,Control_RunDLL Desk.cpl,@0, 1'
Abort

Preview:

System::Call '*(&i4,&i4,&i4,&i4) i .r0' # RECT structure
System::Call 'user32::GetWindowRect(i R1, i r0) i.'
System::Call '*$0(&i4,&i4,&i4,&i4)i(.r1,.r2,.r3,.r4)'
System::Free $0
IntOp $1 $3 - $1 # x = right - left
IntOp $2 $4 - $2 # y = bottom - top

System::Call "user32::CreateWindowEx(i 0, t 'STATIC', t 'Preview', i '${WS_CHILD}|${WS_VISIBLE}|${SS_BITMAP}', i 0, i 0, i r1, i r2, i R1, i 0, i 0, i 0) i. R2"
IntCmp $R2 0 PreviewEnd
File /oname=$PLUGINSDIR\Test.bmp ".\Test.bmp"
System::Call "user32::LoadImage(i 0, t '$PLUGINSDIR\Test.bmp', i ${IMAGE_BITMAP}, i 0, i 0, i ${LR_LOADFROMFILE}) i. R3"
System::Call "user32::SendMessage(i R2, i ${STM_SETIMAGE}, i ${IMAGE_BITMAP}, i R3) i."

# Here's the problem: bitmap will not appear in the preview window until the msgbox is displayed.
# What can I do to change that?
Sleep 2000
MessageBox MB_OK|MB_USERICON "Test bitmap should be visible now."

PreviewEnd:
Abort

FunctionEnd

Section "Blank"
SectionEnd

A window created with CreateWindowEx or CreateDialog (but not DialogBox) needs to process messages for the window to work correctly, so you either have to call GetMessage+DispatchMessage in a loop with the system plugin or create the window and then hide the nsis window in the pre/show callback of your first page so nsis pumps messages for you.

Have you thought about programming this in a "real" language or AutoIt?


Thanks for a traditionally informative reply. I'll see what I can do about message processing. I'm aware nsis wasn't designed for these purposes. I first started using it when I needed to make an installer but then I realized it had possibilities beyond that. I started playing with it and using it to create small programs. I never found the will to move forward and learn a 'real' language, I always managed to find a way to achieve what I needed in nsis but of course I was bound to hit a wall sooner or later.


If you came up with and/or understand the code you posted you are not that far away from coding win32 apps in C (Dealing with RECTs (and structs in general) is actually harder in NSIS)

There are several free options for you: mingw+codeblocks, the free visual studio from MS (The 2003 version can still be found online). Coding in c# can be done on any install of windows with dotnet installed (+notepad) http://www.youtube.com/watch?v=jr1XhCZJoEM


I would recommend C# as an excellent language to begin to learn real programming. You can download Visual Studio 2010 C# Express for free. You can always then branch to C/C++ if the requirement arises (note that C++ Express does not support 64-bit development which is lame).

Stu


I did learn quite a lot about WinAPI fiddling with System plugin. Thanks for advice and encouragement, I really should get into this C# thing but don't be surprised if I turn up with another 'exotic' nsis question. :)


GetMessage+DispatchMessage loop works. :up: