Win32: WM_PAINT == No MessageBox() ?

Windows specific forum
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Win32: WM_PAINT == No MessageBox() ?

Post by va!n »

I have a strange bug in my Win32 program and finally found the part which causes this problem. Inside the procedure 'WindowCallback_Main()' i am using 'CASE #WM_PAINT' without any code yet. The bug causes only if this single line is active. Removing this single line, all works fine. I am not sure, if its my fault. (Does the #WM_XX messages must have a special order?)

My cutted down TestCode:
Just compile the source and try to close the programm (using the Window-Close-Button in the MainWindow). Normaly a MessageBox should be shown now; but this does not happens here (Windows 8.1 x64). You can bring the MessageBox to front, when using 'Alt + Tab'. Pressing 'Alt + F4' fires a CloseEvent, so the MessageBox will be shown correctly.

Now just remove the 'CASE #WM_PAINT' at line 251, inside 'WIndowCallback_Main()' and try to close the window again by pressing the Window-Close-Button; it seems to work fine.
So, if there are no other problems with my source, why does it happens?

If you have any suggestions to get my source more professional like professional C/C++ code, please let me know - thanks!

Code: Select all


; PureBasic 5.21 LTS (Windows - x86 and x64)
; ==============================================================
;
; COMPILER OPTIONS:
;  [ ] Enable inline ASM support
;  [x] Create unicode executable
;  [ ] Create threadsafe executable
;  [ ] Enable OnError lines support
;  [x] Enable XP skin support
;  [ ] Request Administrator mode for Windows Vista
;  [ ] Request User mode for Windows Vista (no virtualization)

; ==============================================================

EnableExplicit

;// ------------------------------------------------------------
;// Some MACROS
;// ------------------------------------------------------------     

Macro LOWORD(dwValue) : dwValue & $FFFF : EndMacro;
Macro HIWORD(dwValue) : dwValue >> 16 : EndMacro;

Macro MAKELPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;
Macro MAKEWPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;


;// ------------------------------------------------------------
;// Define all IDs
;// ------------------------------------------------------------      

;// Define IDs for all STRINGS

#IDS_APPNAME            = "My AppName"
#IDS_CLASSNAME_MAIN     = "My AppName : MainWnd"
#IDS_CLASSNAME_ABOUT    = "My AppName : MainAbout"

Enumeration 200
        #IDC_ABOUT_OK
EndEnumeration


; // ------------------------------------------------------------
; // GLOBAL stuff...
; // ------------------------------------------------------------  

Global hInstance        = GetModuleHandle_(0)
Global g_DefaultFont    = GetStockObject_(#DEFAULT_GUI_FONT);
Global result

;// Windows
Global g_hWnd_Main
Global g_hWnd_About

;// Controls
Global g_hAbout_BtnOK    


;// ------------------------------------------------------------
;// Define all functions 
;// ------------------------------------------------------------

Declare WindowCallback_Main    ( hWnd, message, wParam, lParam);
Declare WindowCallback_About   ( hWnd, message, wParam, lParam); 

Declare Main_OnClose( hWnd, message, wParam, lParam)


;/******************************************************************
;*                                                                 *
;*  Entry WINAPI Main                                              *
;*                                                                 *
;******************************************************************/

Procedure WINAPI_WinMain( hInstance, hPrevInstance, lpCmdLine , nCmdShow )
        
        Static szClassName_Main.s  = #IDS_CLASSNAME_MAIN
        Static szClassName_About.s = #IDS_CLASSNAME_ABOUT
        
        Static wClass1.WNDCLASSEX;
        Static wClass2.WNDCLASSEX
        Static msg.MSG;
        
        
        ;// Check if an instance is already running
        
        ;         If CreateMutex_( 0, 1, #IDS_APPNAME) = 0 Or GetLastError_() <> 0
        ;                 MessageBox_(0, #IDS_MUTEX_INSTANCE, #IDS_APPNAME, 0) 
        ;                 End
        ;         EndIf
        
        ;// ------------------------------------------------------------ 
        
        ;// First: We need to declarate WNDCLASSEX we want to use
        wClass1.WNDCLASSEX;
        wClass2.WNDCLASSEX;
        
        ;// Clear them
        ZeroMemory_(wClass1, SizeOf(WNDCLASSEX));
        ZeroMemory_(wClass2, SizeOf(WNDCLASSEX));
        
        ;// Setup them
        
        ;// first one
        wClass1\cbSize          = SizeOf(WNDCLASSEX);
        wClass1\style           = #CS_HREDRAW | #CS_VREDRAW;
        wClass1\lpfnWndProc     = @WindowCallback_Main();
        wClass1\cbClsExtra      = #Null;
        wClass1\cbWndExtra      = #Null;
        wClass1\hInstance       = hInstance;
        wClass1\hIcon           = #Null;
        wClass1\hCursor         = LoadCursor_(#Null, #IDC_ARROW);
        wClass1\hbrBackground   = #COLOR_WINDOW;
        wClass1\lpszMenuName    = #Null;
        wClass1\lpszClassName   = @szClassName_Main.s;
        wClass1\hIconSm         = #Null;
        
        ;// Second one
        wClass2\cbSize          = SizeOf(WNDCLASSEX);
        wClass2\style           = #CS_HREDRAW | #CS_VREDRAW;
        wClass2\lpfnWndProc     = @WindowCallback_About();
        wClass2\cbClsExtra      = #Null;
        wClass2\cbWndExtra      = #Null;
        wClass2\hInstance       = hInstance;
        wClass2\hIcon           = #Null;
        wClass2\hCursor         = LoadCursor_(#Null, #IDC_ARROW);
        wClass2\hbrBackground   = #COLOR_WINDOW;
        wClass2\lpszMenuName    = #Null;
        wClass2\lpszClassName   = @szClassName_About.s;
        wClass2\hIconSm         = #Null;
        
        ;//Second: register them   
        If (RegisterClassEx_(wClass1)) = 0
                
                MessageBox_(#Null,
                            "Could not register class1",
                            "Window Class Failed",
                            #MB_ICONERROR);
        EndIf
        
        If (RegisterClassEx_(wClass2)) = 0
                
                MessageBox_(#Null,
                            "Could not register class2",
                            "Window Class Failed",
                            #MB_ICONERROR);
        EndIf
        
        
        ;//Now we can proceed with MainWnd creation
        
        #WndMain_Style      = #WS_MAXIMIZEBOX | #WS_MINIMIZEBOX | #WS_THICKFRAME | #WS_SYSMENU | #WS_BORDER | #WS_MAXIMIZE | #WS_CLIPSIBLINGS  | #WS_VISIBLE
        #WndMain_StyleEx    = #WS_EX_WINDOWEDGE  
        
        g_hWnd_Main     = CreateWindowEx_( #WndMain_StyleEx,
                                           szClassName_Main, #IDS_APPNAME, 
                                           #WndMain_Style,
                                           100, 100, 800, 600,
                                           #Null, #Null, hInstance, #Null);
        
        ;//Now we can proceed with AboutWnd creation
        
        #WndAbout_Style     = #WS_VISIBLE | #WS_POPUPWINDOW
        #WndAbout_StyleEx   = #WS_EX_TOPMOST
        
        g_hWnd_About    = CreateWindowEx_( #WndAbout_StyleEx,
                                           szClassName_About, #IDS_APPNAME, 
                                           #WndAbout_Style,
                                           100, 100, 400, 300,
                                           g_hWnd_Main, #Null, hInstance, #Null);
        
        
        ;// Add shadow effect
        SetClassLongPtr_(g_hWnd_About,#GCL_STYLE,$00020000) 
        
        
        ;//Check if both windows are created
        If(g_hWnd_Main) = 0
                MessageBox_(#Null,"Could not create window1","Window Creation Failed",#MB_ICONERROR);
        EndIf
        
        If(g_hWnd_About) = 0
                MessageBox_(#Null,"Could not create window2","Window Creation Failed",#MB_ICONERROR);
        EndIf
        
        
        ;//Now we can show some windows
        ShowWindow_(    g_hWnd_Main, #SW_MAXIMIZE );
        UpdateWindow_(  g_hWnd_Main);
        
        ShowWindow_(    g_hWnd_About, #SW_SHOW );
        UpdateWindow_(  g_hWnd_About);
        
        
        ;//Last Step: handle message
        msg.MSG;
        ZeroMemory_(msg, SizeOf(MSG));
        
        
        While(GetMessage_( msg, #Null, 0, 0))
                TranslateMessage_( msg );
                DispatchMessage_( msg );
        Wend
        
        UnregisterClass_( wClass1, hInstance )
        UnregisterClass_( wClass2, hInstance )
        
        ProcedureReturn msg\wParam
        
EndProcedure


;// ------------------------------------------------------------
;//  START WINAPI_WinMain() 
;// ------------------------------------------------------------       


WINAPI_WinMain( GetModuleHandle_(#Null), 0, GetCommandLine_(), 0)

End



;/******************************************************************
;*                                                                 *
;*  The window's message handler.                                  *
;*                                                                 *
;******************************************************************/

Procedure WindowCallback_Main( hWnd, message, wParam, lParam)
        
        Select message
                        
                Case #WM_COMMAND                     
                        
                Case #WM_CLOSE  
                        Main_OnClose( hWnd, message, wParam, lParam)
                        
                        ;MessageBox_( hWnd, "Exit program?", "EXIT", #MB_YESNO) 
                        ;DestroyWindow_( hWnd)                 
                        
                        
                Case #WM_CREATE           
                        
                Case #WM_DESTROY
                        PostQuitMessage_(0)
                        
                        
                        ;// REMOVE THIS 'CASE #WM_PAINT' AND IT WORKS, WHY?         
                Case #WM_PAINT     
                        
                Case #WM_SIZE
                        
                Default
                        result  = DefWindowProc_( hWnd, message, wParam, lParam)
        EndSelect
        
        ProcedureReturn result
EndProcedure



Procedure WindowCallback_About( hWnd, message, wParam, lParam)
        
        Protected bm.BITMAP;
        Protected ps.PAINTSTRUCT;
        
        Protected hDC
        Protected hDCmem
        Protected hbmOld
        
        Select message
                        
                Case #WM_CLOSE            
                        DestroyWindow_( hWnd )
                        
                        
                Case #WM_COMMAND           
                        Select LOWORD(wParam)
                                Case #IDC_ABOUT_OK
                                        ShowWindow_( g_hWnd_About, #SW_HIDE )
                        EndSelect           
                        
                        
                Case #WM_CREATE
                        g_hAbout_BtnOK = CreateWindowEx_(0, 
                                                         "button", "OK", 
                                                         #WS_CHILD | #WS_VISIBLE | #WS_BORDER, 
                                                         250, 230, 100, 25, 
                                                         hWnd, #IDC_ABOUT_OK, hInstance, #Null);
                        
                Case #WM_DESTROY                                   
                        
                Case #WM_PAINT                         
                        
                Default                     
                        result = DefWindowProc_( hWnd, message, wParam, lParam)
                        
        EndSelect
        
        ProcedureReturn result
        
EndProcedure


;/******************************************************************
;*                                                                 *
;*  Procedures                                                     *
;*                                                                 *
;******************************************************************/

Procedure Main_OnClose( hWnd, message, wParam, lParam)
        
        If MessageBox_( g_hWnd_Main, "Exit program?", "EXIT", #MB_YESNO) = #IDYES
                DestroyWindow_( hWnd)                 
        Else
                ProcedureReturn 0
        EndIf
        
        ;   ProcedureReturn resultW
EndProcedure

va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Win32: WM_PAINT == No MessageBox() ?

Post by RASHAD »

Change

Code: Select all

Procedure WindowCallback_Main( hWnd, message, wParam, lParam)
 
         Select message
                       
                Case #WM_COMMAND                                        
                       
                Case #WM_CLOSE 
                        Main_OnClose( hWnd, message, wParam, lParam)
                       
                        ;MessageBox_( hWnd, "Exit program?", "EXIT", #MB_YESNO)
                        ;DestroyWindow_( hWnd)                      
                       
                Case #WM_CREATE           
                       
                Case #WM_DESTROY
                        PostQuitMessage_(0)
                       
                Case #WM_PAINT
                       
                Case #WM_SIZE                       
                         
        EndSelect
       
        ProcedureReturn DefWindowProc_( hWnd, message, wParam, lParam)   
EndProcedure

Egypt my love
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Win32: WM_PAINT == No MessageBox() ?

Post by ts-soft »

RASHAD is right, you return 0 on #WM_PAINT, so windows think, this event is handled by your code :wink:
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Re: Win32: WM_PAINT == No MessageBox() ?

Post by va!n »

Ah cool. Thanks for the hint. I have changed both Callback procedures and it works well :wink:

Edited:
I have tried to use Main_OnClose() when #WM_CLOSE attached to WindowCallback_Main().
When pressing 'No', dont exit program, it still exist. I have tried ProcedureReturn and ProcedureReturn DefWindowProc_( hWnd, message, wParam, lParam), even with no ProcedureReturns it does not work. What to care here?
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Re: Win32: WM_PAINT == No MessageBox() ?

Post by va!n »

Seems there is something more wrong ^^
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Win32: WM_PAINT == No MessageBox() ?

Post by RASHAD »

Change

Code: Select all

Procedure WindowCallback_Main( hWnd, message, wParam, lParam)
       
        Select message
                       
                Case #WM_COMMAND                     
                       
                Case #WM_CLOSE 
                        If MessageBox_( g_hWnd_Main, "Exit program?", "EXIT", #MB_YESNO) = #IDYES
                                DestroyWindow_( hWnd)                 
                        Else
                                ProcedureReturn 0
                        EndIf         
                       
                       
                Case #WM_CREATE           
                       
                Case #WM_DESTROY
                        PostQuitMessage_(0)                       
                       
                        ;// REMOVE THIS 'CASE #WM_PAINT' AND IT WORKS, WHY?         
                Case #WM_PAINT     
                       
                Case #WM_SIZE
                       

        EndSelect
       
        ProcedureReturn DefWindowProc_( hWnd, message, wParam, lParam)
EndProcedure
Egypt my love
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Re: Win32: WM_PAINT == No MessageBox() ?

Post by va!n »

Okay, so this should work fine to have a better overview over the code:

Code: Select all

...
                Case #WM_CLOSE  
                        result = Main_OnClose( hWnd, message, wParam, lParam)
                        ProcedureReturn result

                Case #WM_CREATE
...


Procedure Main_OnClose( hWnd, message, wParam, lParam)
        
        If MessageBox_( hWnd," it program?", "EXIT", #MB_YESNO) = #IDYES
                 DestroyWindow_( hWnd)                 
        Else
                 ProcedureReturn 0
        EndIf
        
EndProcedure
I need to find a way, to have a good readable / overview over the source with most professional touch as professional C/C++ coders would do, using pure Win32 API.
So, Main_OnClose(), Main_OnCreate() should be the right way, or?
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Win32: WM_PAINT == No MessageBox() ?

Post by RASHAD »

Yes you are right
Because if it is Yes ,Windows will be close direct
If it is No you have to Esc. DefWindowProc_()
I am not a pro but I would say I do not prefer calling Procedure from Procedure unless I can not avoid that
Egypt my love
Post Reply