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

  1. #1
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283

    Creating a function pointer from a button click event?

    I'm trying to do something similar to this in C++:

    Code:
    void ClickMe()
    {
    // do work here
    }
    
    btn.Init(wnd, "Click Me", 10, 10);
    btn.OnClick(ClickMe);  
    btn.Show();
    Although the button object works fine, having something similar to OnClick() would be ideal for what I'm doing. Even if it's not possible, is there anything that might be similar?

    There is SetWindowLong() but I'm not trying to throw the whole window procedure in a ClickMe() function. All I'm interested in is the click event.

    Thanks.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I'm not sure I get your question? The above example works, so...
    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. #3
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Well, this is pure Win32 API but just abstracted out. I would like to click a button and have it send a click event through a function pointer. My ideal way of doing it would be my own OnClick() method that obtains the address of the function I want it to go to.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    So you want to use a function pointer so that when the window proc receives the message, it will automatically call your MyClick function?
    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. #5
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    If that's the easiest way to do it. It's like SetTimer() where it has its own function pointer arguement that is apart from the window procedure itself. You don't have to make a WM_TIMER code block within the window procedure. You can set the function apart from it, and every time the timer is called, the function you specified is called automatically. I'd like that for my mouse class using an OnClick method, if possible.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about this...
    Code:
    typedef LRESULT (MessageCallbackPtr)(WPARAM, LPARAM);
    std::map<int, MessageCallbackPtr*> mCallback;
    LRESULT WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	// ...
    	iterator iFunction;
    	iFunction = mCallback.find(message);
    	if ( iFunction != mCallback.end() )
    		return iFunction->second(wParam, lParam);
    	// ...
    }
    You can simply add a message to the map and then the function to which the message shall be redirected:

    Code:
    LRESULT MyClickHandler(WPARAM wParam, LPARAM lParam) { }
    int main()
    {
    	// ...
    	mCallback[WM_CLICK] = &MyClickHandler;
    	// ...
    }
    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.

  7. #7
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Thanks, this will get me started. Is WindowProc the button's own window procedure, or the parent window? I don't know how to modify a window procedure of a predefined "button" class. And, WM_CLICK isn't being recognized. I'll just assume you mean WM_LBUTTONDOWN.

    And, where // ... is, is that the normal switch and WM_COMMAND message?

    I'm getting this too for...
    btn.m_callBack[WM_LBUTTONDOWN] = &MyClickHandler;

    error C2440: '=' : cannot convert from 'LRESULT (__cdecl *)(WPARAM,LPARAM)' to 'std::map<_Kty,_Ty>::mapped_type
    Last edited by dxfoo; 01-27-2008 at 09:57 PM.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I think every window has its own procedure? It's been a long time since I did pure Win32 programming. It might present additional problems if your button shares the same procedure as the parent window. I might be able to devise a solution to that using classes, though.

    Quote Originally Posted by dxfoo View Post
    Thanks, this will get me started. Is WindowProc the button's own window procedure, or the parent window? And, WM_CLICK isn't being recognized. I'll just assume you mean WM_LBUTTONDOWN.
    Yeah, whatever the message is. It's been long since I bothered with pure Win32.
    Last edited by Elysia; 01-27-2008 at 09:52 PM.
    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.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Here's an updated code where you can mix several windows into one procedure.
    The //... means whatever other code you need to put there.
    Code:
    typedef LRESULT (MessageCallbackPtr)(WPARAM, LPARAM);
    typedef std::map<int, MessageCallbackPtr*> CallbackWindowMap;
    typedef std::map<HWND, CallbackWindowMap> CallbackMap;
    CallbackMap mCallback;
    LRESULT WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	// ...
    	CallbackMap::iterator iWindow;
    	iWindow = mCallback.find(hwnd);
    	if ( iWindow != mCallback.end() )
    	{
    		CallbackWindowMap::iterator iFunction;
    		iFunction = iWindow->second.find(message);
    		if ( iFunction != iWindow->second.end() )
    			return iFunction->second(wParam, lParam);
    	}
    	// ...
    	return 0;
    }
    
    LRESULT MyClickHandler(WPARAM wParam, LPARAM lParam) { return 0; }
    void Help()
    {
    	// ...
    	mCallback[/*My window*/0x0][WM_LBUTTONDOWN] = &MyClickHandler;
    	// ...
    	//WindowProc(0x0, WM_LBUTTONDOWN, 0, 0);
    }
    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.

  10. #10
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Would it be too much of a pain to write a working example? Code for a blank window can be found here for starters: http://winprog.org/tutorial/simple_window.html

    I'm just getting errors left and right. I'll keep playing around with it though.

    Edit: I didn't see the updated code before posting this. I'll try it out.

  11. #11
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    I can't seem to get it working.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You need to post the code. I'm not psychic!
    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.

  13. #13
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    You're not?

    I did a seperate project that has a blank window and a button.

    Code:
    #include <windows.h>
    #include <map>
    #include <iostream>
    #include <string>
    
    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);
    }
    
    
    // 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::iterator<int, MessageCallbackPtr *> 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;
    }

    Errors:
    Code:
    Compiling...
    winmain.cpp
    c:\Documents and Settings\Phil\My Documents\Visual Studio Projects\Win32 Practice\winmain.cpp(32) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::_Tree<_Traits>::iterator' (or there is no acceptable conversion)
            with
            [
                _Traits=std::_Tmap_traits<int,__w64 long (__cdecl *),std::less<int>,std::allocator<std::pair<const int,__w64 long (__cdecl *)>>,false>
            ]
    c:\Documents and Settings\Phil\My Documents\Visual Studio Projects\Win32 Practice\winmain.cpp(33) : error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::iterator<_Category,_Ty>' (or there is no acceptable conversion)
            with
            [
                _Category=int,
                _Ty=MessageCallbackPtr (__cdecl *)
            ]
    c:\Documents and Settings\Phil\My Documents\Visual Studio Projects\Win32 Practice\winmain.cpp(34) : error C2819: type 'std::iterator<_Category,_Ty>' does not have an overloaded member 'operator ->'
            with
            [
                _Category=int,
                _Ty=MessageCallbackPtr (__cdecl *)
            ]
            did you intend to use '.' instead?
    c:\Documents and Settings\Phil\My Documents\Visual Studio Projects\Win32 Practice\winmain.cpp(34) : error C2227: left of '->second' must point to class/struct/union
            type is 'std::iterator<_Category,_Ty>'
            with
            [
                _Category=int,
                _Ty=MessageCallbackPtr (__cdecl *)
            ]
            did you intend to use '.' instead?
    
    Build log was saved at "file://c:\Documents and Settings\Phil\My Documents\Visual Studio Projects\Win32 Practice\Debug\BuildLog.htm"
    Win32 Practice - 4 error(s), 0 warning(s)

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    LRESULT MyClickHandler(WPARAM wParam, LPARAM lParam) 
    {
    	MessageBox(NULL, "Got it", "Click!", MB_OK);
    	return 0; // All functions must return a value!
    }
    Code:
    std::iterator<int, MessageCallbackPtr *> iFunction;
    Oops. You did it wrong. It should be:
    Code:
    std::map<int, MessageCallbackPtr *>::iterator iFunction;
    I also note you didn't use my second sample.
    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.

  15. #15
    Software engineer
    Join Date
    Aug 2005
    Location
    Oregon
    Posts
    283
    Simple code first Let me try this out...

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