From: Laurent R. <ro...@cl...> - 2003-12-10 19:32:21
|
> Glenn Linderman wrote: > > But I think if you use Win32::API to call call PeekMessage with the > > PM_REMOVE set, that you may not get the repeated behavior... me thinks > > the bug is inside DoEvents, somehow.... it just hit me... maybe the > > PM_REMOVE constant is wrong? (Pure speculation here, but something is > > wrong, and it isn't obvious.) > > no, the PM_REMOVE seems to be correct. I also tried to debug this one > really hard, to no avail. > I think problem come from use of PeekMessage return value. PeekMessage Return Values: If a message is available, the return value is nonzero. If no messages are available, the return value is zero. In current DoEvents code, when PeekMessage return 0, loop exit only after proceding last MSG. while(stayhere) { stayhere = PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE); #ifdef PERLWIN32GUI_STRONGDEBUG printf("XS(DoEvents): PeekMessage returned %d\n", stayhere); #endif if(msg.message == WM_EXITLOOP) { stayhere = 0; msg.wParam = (WPARAM) -1; } else { if(stayhere == -1) { stayhere = 0; msg.wParam = (WPARAM) -2; // an error occurred... } else { ... } } } I think code below resolve double event call. Laurent ########################################################################### # (@)METHOD:DoEvents() DWORD DoEvents(hwnd=NULL) HWND hwnd PREINIT: MSG msg; HWND phwnd; HWND thwnd; int stayhere; BOOL fIsDialog; HACCEL acc; LPPERLWIN32GUI_USERDATA perlud; CODE: stayhere = 1; fIsDialog = FALSE; while(stayhere) { stayhere = PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE); #ifdef PERLWIN32GUI_STRONGDEBUG printf("XS(DoEvents): PeekMessage returned %d\n", stayhere); #endif if (stayhere) { if(msg.message == WM_EXITLOOP) { stayhere = 0; msg.wParam = (WPARAM) -1; } else { // #### trace back to the window's parent phwnd = msg.hwnd; while(thwnd = GetParent(phwnd)) { phwnd = thwnd; } // #### now see if the parent window is a DialogBox fIsDialog = FALSE; acc = NULL; perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLong(phwnd, GWL_USERDATA); if( ValidUserData(perlud) ) { fIsDialog = perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI; acc = perlud->hAcc; } if(acc && TranslateAccelerator(phwnd, acc, &msg)) continue; if(fIsDialog && IsDialogMessage(phwnd, &msg)) continue; TranslateMessage(&msg); DispatchMessage(&msg); } } else msg.wParam = (WPARAM) 0; } RETVAL = msg.wParam; OUTPUT: RETVAL |