- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In porting my app to Windows Vista I've encountered a problem where the message loop in the following code exits even before the window is displayed. The same code works fine in Windows XP. The value of mesg%MESSAGE at the return is WM_QUIT, but Spy++ doesn't show a WM_QUIT being received by the window. Any idea what I'm doing wrong?
subroutine displayBltSplashScreen
use ftsGlobals
use globals
use user32
implicit none
include 'common.inc'
include 'mainHeader.inc'
type (T_MSG) mesg
integer hbkgBrush, iopt, iopt1, i, j, dx, dy, hwndDlg
logical retlog
character(SIZEOFAPPNAME) lpszSplash
character(SIZEOFAPPNAME) lpszAppName
character*10 button1Label, button2Label
type (T_WNDCLASSEX) wcSplash2
lpszSplash = "splash"C
lpszAppName =""C
hbkgBrush = COLOR_BACKGROUND
iopt = 0
iopt1 = WS_POPUP
haventDoneSplash = .false.
!tail number selection window
wcSplash2%cbSize = sizeof(wcSplash2)
wcSplash2%lpszClassName = loc(lpszSplash)
wcSplash2%lpfnWndProc = LOC(splashProc)
wcSplash2%style = IOR(CS_VREDRAW , CS_HREDRAW)
wcSplash2%hInstance = ghInstance
!wcSplash2%hCursor = LoadCursor( NULL, IDC_ARROW )
wcSplash2%hIcon = NULL
wcSplash2%hIconSm = NULL
wcSplash2%hCursor = NULL
wcSplash2%hbrBackground = hbkgBrush
wcSplash2%lpszMenuName = NULL
wcSplash2%cbClsExtra = 0
wcSplash2%cbWndExtra = 0
i = registerClassEx(wcSplash2)
hwndDlg = CreateWindowEx ( iopt, lpszSplash, &
lpszAppName, &
iopt1, &
100, &
100, &
600, &
400, &
NULL, &
NULL, &
ghInstance, &
NULL &
)
ghwndSplash = hwndDlg
retlog = ShowWindow( hwndDlg, SW_SHOW )
do while( GetMessage (mesg, NULL, 0, 0) )
retlog = TranslateMessage( mesg )
i = DispatchMessage( mesg )
end do
return
end
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Insert diagnostic code to verify the value of hwndDlgit is a valid handle. Note, Vista may have added an additional return value that is not a valid handle that is also not NULL nor one of the NT/XP error codes.
It also is advised to check the return of ShowWindow.
Your do while loop assumes everything is set for calling GetMessage
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try
hwndDlg = CreateWindowEx (WS_EX_TOPMOST, lpszSplash, &
lpszAppName, &
IOR(WS_POPUPWINDOW, WS_CAPTION),&
100, &
100, &
400,&
600,&
NULL, &
NULL, &
ghINSTANCE, &
NULL )
and
retlog = ShowWindow( hwndDlg, SW_SHOWNORMAL )
You should also add an interface block for splashproc e.g.
interface
integer function splashproc ( hWnd, mesg, wParam, lParam )
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_splashproc@16' :: splashproc
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'splashproc' :: splashproc
!DEC$ ENDIF
integer(4) hwnd,mesg,wparam,lparam
end function
end interface
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The hwndDlg value looks like a valid window handle (#0002045A). ShowWindow returns a nonzero value (#00000018).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anyway thanks for the input Jim and Anthony!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you can also get funny things happening with your 'while(GetMessage...) construction. Better I think is the following construction for your message loop:
do while( GetMessage (mesg, hwndDlg, 0, 0) .GT.0)
retlog = TranslateMessage( mesg )
i = DispatchMessage( mesg )
end do
Remember that Getmessage can return -1 as well as 0 and 1.
If you call this routine more than once, you should also check whether the window class has already been registered before you use registerclassEx (or unregister it before exiting the routine), and only use createwindowExafter you have testedthat registerclassex has returned a non-zero value.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First, one should use NULL hwnd for GetMessage in a message loop for any practical application. That ensures that the correct target window will be eventually reached. Quote: "Value NULL: GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread via PostThreadMessage".
Second, the style:
do while( GetMessage (mesg, hwndDlg, 0, 0) .GT. 0)is not good. GetMessage will return -1 in case of an error (e.g. bad hwnd); you likely don't want to exit your application if perchance you coded a wrong SendMessage call somewhere -- rather, you'd like the message ignored. Instead, one should use .NE. 0: GetMessage does not return a LOGICAL but an INTEGER(BOOL). Unfortunately, Ifort by default lets you get away with such free integer/logical mixing, where one can easily shoot oneself in the foot under the right circumstances.
Third, frankly, I don't get the purpose of check on RegisterClassEx return value; it cannot possibly fail. If it does fail, that means a) that you won't get the window at all and b) that you have a bug in your code that you should fix. While I'm all for defensive programming, this is taking it too far.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Cartman4:
I think I found the problem. The windows procedure for a previous window was erroneously calling PostQuitMessage after it's message loop has already exited, and the resulting WM_QUIT was making it's way to the current message loop. I don't know why the problem only manifested itself in Vista though.
See this interesting explanation and discussion afterwards (note that it dates from 2005):
http://blogs.msdn.com/oldnewthing/archive/2005/11/04/489028.aspx
According to that, multiple WM_QUIT messages (used to) "coalesce", i.e. system just merged them into one (because a "real" message has never existed in the first place). However, the behavior was not documented, therefore Vista developers were free to change it by changing the system internals -- purposefully or accidentally. You seem to be hit by that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jugoslave and Anthony
When I used to program device drivers on Windows NT in C we used the technique of using a macro named ASSERT(expression, "message") and place that into the code following function calls that would ordinarily never fail in a fully debugged application. The macro is expanded in the Debug version but not in the Release version. In Fortran you can use the Fortran Pre-Processor (FPP) to provide the same functionality
#ifdef _DEBUG
#define ASSERT(e, msg) IF(.NOT. (e)) CALL doASSERT(msg)
#else
#define ASSERT(e, msg)
#endif
Something like the above is often very useful during the initial phases of developing an applicaiton.
Jim Dempsey
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page