Win32 Button

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • newguy194
    New Member
    • May 2007
    • 25

    Win32 Button

    Why am I unable to produce a button with this Win32 program? All I have been able to produce is the empty window.



    Code:
    #include <windows.h>
    
    // Declare WndProcedure
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    			   WPARAM wParam, LPARAM lParam);
    
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
    {
        HWND       button;
    	MSG        Msg;
    	HWND       hWnd;
    	HRESULT	   hRet;
    	WNDCLASSEX WndClsEx;
    
    	// Populate the WNDCLASSEX structure
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	WndClsEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    	WndClsEx.lpszMenuName  = NULL;
    	WndClsEx.lpszClassName = "GlowdotWin32TutorialPartI";
    	WndClsEx.hInstance     = hInstance;
    	WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    	// Register the class
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindow("GlowdotWin32TutorialPartI",
    			  "Glowdot Win32 Tutorial - Part I",
    			  WS_OVERLAPPEDWINDOW,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  NULL,
    			  NULL,
    			  hInstance,
    			  NULL);
    	
        button = CreateWindow( 
        "BUTTON",                                    // predefined class
        "OK",                                        // button text
        WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,    // styles 
                                                     // Size and position values are given 
                                                     // explicitly, because the CW_USEDEFAULT 
                                                     // constant gives zero values for buttons. 
        100,                                          // starting x position
        100,                                          // starting y position 
        200,                                         // button width 
        200,                                         // button height 
        hWnd,                                        // parent window 
        NULL,                                        // No menu 
        hInstance,                                   // Our apps HINSTANCE 
        NULL                                         // pointer not needed 
    );
    
        if ( !button)
           return 0;
    	// Verify window creation
    	if( !hWnd ) // If the window was not created,
    		return 0; // stop the application
    
    	// Show the window
    	ShowWindow(hWnd, SW_SHOWNORMAL);
    	ShowWindow(button, SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
        UpdateWindow(button);
    	// our message pump
    	while( (hRet = GetMessage( &Msg, NULL, 0, 0 )) != 0)
    	{ 
    		if (hRet == -1)
    		{
            // handle the error and possibly exit
    		}
    		else
    		{
    			TranslateMessage(&Msg); 
    			DispatchMessage(&Msg); 
    		}
    	}
    }
    
    //////////////////
    // WndProcedure //
    //////////////////
    
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
        switch(Msg)
        {
        case WM_DESTROY:
            // user wants to exit
            PostQuitMessage(WM_QUIT);
            break;
        default:
            // Hand off unprocessed messages to DefWindowProc
            return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        
        return 0;
    }
  • Studlyami
    Recognized Expert Contributor
    • Sep 2007
    • 464

    #2
    what compiler are you using?

    That program fails to create anything on visual studios 2005. I added
    if(!hWnd)
    {
    return 0;
    }

    and i get a return 0. two tired to try and figure out why.

    Comment

    • newguy194
      New Member
      • May 2007
      • 25

      #3
      Originally posted by Studlyami
      what compiler are you using?

      That program fails to create anything on visual studios 2005. I added
      if(!hWnd)
      {
      return 0;
      }

      and i get a return 0. two tired to try and figure out why.
      My compiler is gcc

      The program creates a window for me, but does not generate or display the button, and the check I added for the button is telling me it is not created.

      Comment

      • newguy194
        New Member
        • May 2007
        • 25

        #4
        Something really, really, really, really weird. On the PC which I do most of my programming on the program fails to run correctly and nothing appears, but on my Vista pc the program runs fine, generates a button and doesn't fail any of the checks.

        Comment

        • Studlyami
          Recognized Expert Contributor
          • Sep 2007
          • 464

          #5
          LOL! Alright on my home pc (Vista, Visual Studios 2005 (latest updates)) this program wouldn't even generate the original window. At work (XP, Visual Studios 2003(Uknown updates)) this program loads fine and creates the button. I would say this would of been an issue with Vista, but newguy built it fine on vista. Newguy what program did you use to compile it? maybe we can narrow the problem down that way.

          Comment

          • newguy194
            New Member
            • May 2007
            • 25

            #6
            Sorry, my compiler is gcc, not Dev silly me.

            Comment

            • Cucumber
              New Member
              • Sep 2007
              • 90

              #7
              You can use this function to show what was the last error at any point within your win32 program. You may use it after creating or showing the button to see what the operating system that is not showing the button has to say about it.

              void ShowLastError( )
              {
              TCHAR *buffer;
              int errorcode = ::GetLastError( );
              if ( errorcode )
              {
              ::FormatMessage (FORMAT_MESSAGE _ALLOCATE_BUFFE R|FORMAT_MESSAG E_FROM_SYSTEM,
              NULL,errorcode, MAKELANGID(LANG _NEUTRAL, SUBLANG_DEFAULT ),
              (LPTSTR)&buffer ,0,NULL);
              ::MessageBox(HW ND_DESKTOP, buffer, 0,0);
              ::LocalFree( buffer );
              }
              }

              By the way, using UpdateWindow with the button seems a bit awkward to me, the Win32 protocol says you should call UpdateWindow for the parent Window, not for the child controls.
              I would also avoid calling ShowWindow for the control too.

              Comment

              • Glenn Ward
                New Member
                • Oct 2010
                • 1

                #8
                Long Over do Explanation!

                I know this is an old topic but just in case someone comes upon it by chance I wanted to post a reply so people can see. First of all this isn't good programming practice. Your HWND button shouldn't be in the WinMain function because your Callback can't access it, it must be a global if you wish to use it this way. Also you shouldn't create it in WinMain, you should use the case WM_CREATE to run the function CreateWindow.

                Code:
                #define ID_EXITBUTTON 69000
                #include <Windows.h>
                
                LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
                
                HWND Button;
                char *window = "Change this text to your window's class name!";
                
                int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
                {
                	WNDCLASSEX wc;
                	HWND hWnd;
                	MSG msg;
                
                	wc.cbSize        = sizeof(WNDCLASSEX);
                	wc.style         = 0;
                	wc.lpfnWndProc   = WndProc;
                	wc.cbClsExtra    = 0;
                	wc.cbWndExtra    = 0;
                	wc.hInstance     = hInstance;
                	wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
                	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
                	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
                	wc.lpszMenuName  = NULL;
                	wc.lpszClassName = window;
                	wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
                
                	if(!RegisterClassEx(&wc))
                	{
                		MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
                		return 0;
                	}
                
                	// Step 2: Creating the Window
                	hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, window, "Character Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
                
                	if(hWnd == NULL)
                	{
                		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
                		return 0;
                	}
                
                	ShowWindow(hWnd, nCmdShow);
                	UpdateWindow(hWnd);
                
                	// Step 3: The Message Loop
                	while(GetMessage(&msg, NULL, 0, 0) > 0)
                	{
                		TranslateMessage(&msg);
                		DispatchMessage(&msg);
                	}
                	return msg.wParam;
                }
                
                LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
                {
                	switch(msg)
                	{
                	case WM_CREATE:
                		{
                			Button = CreateWindow("button", "Exit", BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE, 250, 30, 100, 20, hWnd, (HMENU)ID_EXITBUTTON, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
                			break;
                		}
                	case WM_COMMAND:
                		{
                			switch(wParam)
                			{
                			case ID_EXITBUTTON:
                				{
                					PostQuitMessage(0);
                					break;
                				}
                			}
                			break;
                		}
                	case WM_DESTROY:
                		{
                			PostQuitMessage(0);
                			break;
                		}
                	default:
                		{
                			return DefWindowProc(hWnd, msg, wParam, lParam);
                		}
                	}
                	return 0;
                }
                All this button does is close your window down, you can change the case ID_EXITBUTTON to whatever you choose so that you can manipulate it to do what you please though. Notice I defined ID_EXITBUTTON at the very top, you normally do this in the resource.h file but since I did it here just to give you a working program. The key thing here is that WndProc can now access the button HWND unlike your copy earlier. WndProc must be able to do this because it is a child window, if not you have problems as you can see. Hopefully this explains to future programmers why we code things a certain way like utilize WM_CREATE instead of putting things in WinMain. In fact, WinMain shouldn't really change at all, it should remain the same from program to program. Notice I put the char *window as a global. Normally this would be in WinMain and the only thing you would change but I wanted to show that WinMain should be 100% constant except this variable so that is why I did it. Also you can't compile this in UNICODE because it doesn't convert chat * properly so if you get an error in Visual C++, that is why.

                Comment

                Working...