Thread: Creating a function pointer from a button click event?

  1. #16
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Okay, here's the code, but the application doesn't recognize the button click. I'll try some debugging. Right now, MyClickHandler isn't being called correctly. Oh, and "if ( iFunction != mCallback.end() )" is skipping the next line.

    Code:
    #include <windows.h>
    #include <iostream>
    #include <string>
    #include <map>
    
    typedef LRESULT (MessageCallbackPtr)(WPARAM, LPARAM);
    std::map<int, MessageCallbackPtr*> mCallback;
    
    const char g_szClassName[] = "myWindowClass";
    
    LRESULT MyClickHandler(WPARAM wParam, LPARAM lParam) 
    {
    	MessageBox(NULL, "Got it", "Click!", MB_OK);
    	return 0;
    }
    
    
    // Step 4: the Window Procedure
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_CLOSE:
                DestroyWindow(hwnd);
            break;
            case WM_DESTROY:
                PostQuitMessage(0);
            break;
    
    		case WM_COMMAND:
    		{
    			std::map<int, MessageCallbackPtr *>::iterator iFunction;
    			iFunction = mCallback.find(msg);
    			if ( iFunction != mCallback.end() )
    				return iFunction->second(wParam, lParam);
    		}
    		break; 
    
            default: 
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
        WNDCLASSEX wc;
        HWND hwnd, hWndButton;
        MSG Msg;
    
        //Step 1: Registering the Window Class
        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 = g_szClassName;
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
        if(!RegisterClassEx(&wc)) { 
            return 0;
        }
    
        // Step 2: Creating the Window
        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName,
            "Win32 Practice",WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
            NULL, NULL, hInstance, NULL);
        if(hwnd == NULL) { 
            return 0;
        }
    
    	hWndButton = CreateWindowEx(NULL, "button", "Click Me", 
    		WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 50, 50, 100, 24, hwnd, 
    		(HMENU)(100), hInstance, NULL);
    	if (hWndButton == NULL)
    		return false;
    
    	mCallback[WM_LBUTTONDOWN] = &MyClickHandler;
    
        ShowWindow(hwnd, nCmdShow);
        UpdateWindow(hwnd);
    
        // Step 3: The Message Loop
        while(GetMessage(&Msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&Msg); 
            DispatchMessage(&Msg);
        }
        return (int) Msg.wParam;
    }
    Last edited by dxfoo; 01-27-2008 at 11:18 PM.

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, I don't know (remember) what message is sent.
    So take a look at your window proc when a button is pressed and note the message. The message is what you need to use in the callback map.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Whatever it is, it's 273! Thanks! You're brilliant even when you're away from Win32 these days haha...

    Edit: I looked into 273, it ended up being 0x111, otherwise, WM_COMMAND. So, I gotta do this...

    mCallback[WM_COMMAND] = &MyClickHandler;

    WM_COMMAND isn't really clear as of what I'm specifying. But still, it works, but it would be nice to be more specific if possible. It only accepts left button clicks, though, so I guess this is a good thing Anyway, thanks for the help tonight.
    Last edited by dxfoo; 01-27-2008 at 11:56 PM.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Here's a better suggestion:
    Code:
    #include <windows.h>
    #include <iostream>
    #include <string>
    #include <map>
    
    typedef LRESULT (MessageCallbackPtr)(WPARAM, LPARAM);
    std::map<int, MessageCallbackPtr*> mCallback;
    
    const char g_szClassName[] = "myWindowClass";
    
    LRESULT MyClickHandler(WPARAM wParam, LPARAM lParam) 
    {
    	MessageBox(NULL, "Got it", "Click!", MB_OK);
    	return 0;
    }
    
    
    // Step 4: the Window Procedure
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_CLOSE:
                DestroyWindow(hwnd);
            break;
            case WM_DESTROY:
                PostQuitMessage(0);
            break;
    
    		case WM_COMMAND:
    		{
    			std::map<int, MessageCallbackPtr *>::iterator iFunction;
    			iFunction = mCallback.find( LOWORD(wParam) );
    			if ( iFunction != mCallback.end() )
    				return iFunction->second(wParam, lParam);
    		}
    		break; 
    
            default: 
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
        WNDCLASSEX wc;
        HWND hwnd, hWndButton;
        MSG Msg;
    
        //Step 1: Registering the Window Class
        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 = g_szClassName;
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
        if(!RegisterClassEx(&wc)) { 
            return 0;
        }
    
        // Step 2: Creating the Window
        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName,
            "Win32 Practice",WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
            NULL, NULL, hInstance, NULL);
        if(hwnd == NULL) { 
            return 0;
        }
    
    	hWndButton = CreateWindowEx(NULL, "button", "Click Me", 
    		WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 50, 50, 100, 24, hwnd, 
    		(HMENU)(100), hInstance, NULL);
    	if (hWndButton == NULL)
    		return false;
    
    	mCallback[/* Control ID here, as is sent by the low word of the wParam */] = &MyClickHandler;
    
        ShowWindow(hwnd, nCmdShow);
        UpdateWindow(hwnd);
    
        // Step 3: The Message Loop
        while(GetMessage(&Msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&Msg); 
            DispatchMessage(&Msg);
        }
        return (int) Msg.wParam;
    }
    If you use the control identifier instead, it should only react for that control. Or you could use the window handle instead. But I don't know if the control's handle is sent via the hwnd argument in the window proc when a control notifies its window.

    I'm not used to Pure Win32 programming nowadays. I typically use MFC.
    Just add a button to the dialog, give it an ID and double-click it to create an event handler. Handy, isn't it? That's why I remember so little about this mess.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Definitely. I use Win32 for game programming and .Net for the job I'm trying to build a slim win32 GUI classes for my library, and MFC is just 100x more powerful than I need for games. .Net 3.5 has 200mb of runtime crap too Win32 is managable. But yeah... if I was building a game editor I'd consider MFC or C++/CLI.

    Oh yeah, the best part of my code:

    Code:
    void OnClick(MessageCallbackPtr clickEvent)
    {
    	mCallback[WM_COMMAND] = &clickEvent;
    }
    Last edited by dxfoo; 01-28-2008 at 08:34 PM.

  6. #21
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, as you know, WM_COMMAND isn't the best message to use for it.
    It's better to use the button's specific ID so it won't call the handler for whatever menu or button you click!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  3. Replies: 7
    Last Post: 07-04-2007, 12:46 PM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM