Thread: Custom Control

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    288

    Custom Control

    Hi,

    Im trying to create my own custom control class, and im have a few problems with the Main and Proc functions, heres the code i use:

    Code:
    class aButton
    {
    	public:
    		void Create(//params here);
    	private:
    
    		void Main();
    		WNDPROC Proc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
    };
    
    void aButton::Create(//params here)
    {
    	DWORD dwThread;
    	m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Main, NULL, 0, &dwThread);
    }
    
    void aButton::Main()
    {
    	MSG Message;
    	WNDCLASS Window = {0};
    
    	Window.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
    	Window.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	Window.hCursor = LoadCursor(NULL, IDC_ARROW);
    	Window.hInstance = m_hInstance;
    	Window.lpfnWndProc = Proc;
    	Window.lpszClassName = "aButton";
    	Window.style = CS_HREDRAW | CS_VREDRAW;
    	
    	RegisterClass(&Window);
    	
    	m_hButton = CreateWindow("aButton",
    							 "",
    							 WS_CHILD,
    							 0,
    							 0,
    							 0,
    							 0,
    							 m_hParent,
    							 0,
    							 m_hInstance,
    							 0);
    	
    	ShowWindow(m_hButton, SW_SHOW);
    	UpdateWindow(m_hButton);
    
    	while (GetMessage(&Message, NULL, 0, 0))
    	{
    		TranslateMessage(&Message);
    		DispatchMessage(&Message);
    	}
    
    	UnregisterClass("aButton", m_hInstance);
    }
    
    WNDPROC aButton::Proc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
    	switch (Message)
    	{
    		//Handle all messages (paint msgs, mouse msgs.. etc)
    
    		default: return (WNDPROC)DefWindowProc(hWnd, Message, wParam, lParam);
    	}
    
    	return (WNDPROC)0;
    }
    anyway, when i try to compile, i get 2 errors:

    Code:
    D:\Programming\C++\aButton.cpp(86) : error C2440: '=' : cannot convert from 'long (__stdcall *(__thiscall aButton::*)(struct HWND__ *,unsigned int,unsigned int,long))(struct HWND__ *,unsigned int,unsigned int,long)' to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'
    
    D:\Programming\C++\aButton.cpp(74) : error C2440: 'type cast' : cannot convert from '' to 'unsigned long (__stdcall *)(void *)'
            None of the functions with this name in scope match the target type
    Basically, im trying to handle all the messages for my custom control in 1 class.. is there an easier way? or a different way? if so, please let me know

    thanks

  2. #2
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Glancing at your code, the main problem is that you're trying to assign the address of a member function to lpfnWndProc

    Code:
    Window.lpfnWndProc = Proc;
    lpfnWndProc needs the function to be a static class function, or a global function.

    See this old post.

    And here's a nice tutorial on custom controls:
    Custom Controls From Scratch

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    when i declare it as a static i get this error:

    Code:
    error C2724: 'Proc' : 'static' should not be used on member functions defined at file scope

  4. #4
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Did you declare it as static inside the class?

    If you declare it as static outside of the class, it's wrong.

  5. #5
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    its inside the class

  6. #6
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Strange. Show me the new code.

  7. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    here it is:

    Code:
    #include "aButton.h"
    
    class aButton
    {
    	public:
    		void Create(HINSTANCE hInstance, HWND hParent, char *sText, HMENU hMenu);
    
    	private:
    
    		void Main();
    		static WNDPROC Proc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
    };
    
    void aButton::Create(HINSTANCE hInstance, HWND hParent, char *sText, HMENU hMenu)
    {
    	m_hInstance = hInstance;
    	m_hParent = hParent;
    
    	m_sText = new char[strlen(sText)];
    	strcpy(m_sText, sText);
    
    	m_hMenu = hMenu;
    
    	DWORD dwThread;
    	m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Main, NULL, 0, &dwThread);
    }
    
    void aButton::Main()
    {
    	MSG Message;
    	WNDCLASS Window = {0};
    
    	Window.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
    	Window.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	Window.hCursor = LoadCursor(NULL, IDC_ARROW);
    	Window.hInstance = m_hInstance;
    	Window.lpfnWndProc = Proc;
    	Window.lpszClassName = "aButton";
    	Window.style = CS_HREDRAW | CS_VREDRAW;
    	
    	RegisterClass(&Window);
    	
    	m_hButton = CreateWindow("aButton",
    							 "",
    							 WS_CHILD,
    							 0,
    							 0,
    							 0,
    							 0,
    							 m_hParent,
    							 0,
    							 m_hInstance,
    							 0);
    	
    	ShowWindow(m_hButton, SW_SHOW);
    	UpdateWindow(m_hButton);
    
    	while (GetMessage(&Message, NULL, 0, 0))
    	{
    		TranslateMessage(&Message);
    		DispatchMessage(&Message);
    	}
    
    	UnregisterClass("aButton", m_hInstance);
    }
    
    static WNDPROC aButton::Proc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
    	switch (Message)
    	{
    		//handle msgs here
    
    		default: return (WNDPROC)DefWindowProc(hWnd, Message, wParam, lParam);
    	}
    
    	return (WNDPROC)0;
    }

  8. #8
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Like I said...

    If you declare it as static outside of the class, it's wrong.

  9. #9
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    oh sorry, i thought you meant declaring it as a static global function :\

    ill try recompiling

  10. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    by the way, can u please explain what you mean by outside the class?
    shud i define it as static inside the

    Code:
    class aButton {...};
    but not in the

    Code:
    WNDPROC Proc(...)
    because i tried that and it still gives me about 67 errors instead of 2

  11. #11
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Yup, that's what I meant.

    Can you post a few of the errors?

    [edit]

    I'm on Linux right now, so I can't check this...but is

    WNDPROC == LRESULT CALLBACK ?
    Last edited by Dante Shamest; 03-03-2005 at 10:54 AM.

  12. #12
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    if i do what you said, i get errors for all the code thats inside the WNDPROC Proc function...

    errors like:

    for this code:

    Code:
    case WM_CREATE:
    case WM_SIZE:
    {
    	GetClientRect(hWnd, &m_rButton);
    
    	m_rText.bottom = m_rButton.bottom - 1;
    	m_rText.left = m_rButton.left + 1;
    	m_rText.right = m_rButton.right - 1;
    	m_rText.top = m_rButton.top + 1;
    }
    break;
    i get these errors:

    Code:
    D:\Programming\C++\aButton.cpp(93) : error C2228: left of '.m_rText' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(93) : error C2228: left of '.bottom' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(93) : error C2228: left of '.bottom' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(94) : error C2228: left of '.left' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(94) : error C2228: left of '.left' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(95) : error C2228: left of '.right' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(95) : error C2228: left of '.right' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(96) : error C2228: left of '.top' must have class/struct/union type
    D:\Programming\C++\aButton.cpp(96) : error C2228: left of '.top' must have class/struct/union type
    not sure why they repeat twice tho

    [edit]

    heres the typedef for WNDPROC

    Code:
    typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);

  13. #13
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    A static class function cannot access member variables. This is the reason for most of the errors.

    This may help.

  14. #14
    Registered User
    Join Date
    Aug 2003
    Posts
    288
    so basically.. i need to make everything static?

    wow.. i didnt think defining a callback in a class would require so much effort :P

  15. #15
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    If you make everything static, that means you effectively can only have one functioning instance of the class - a singleton.

    The most common solution to this problem is to store the address of each class object in the window's extra bytes using SetWindowLong and get it back with GetWindowLong.

    Click me.

    [edit]

    Actually, this board is full of past questions that resemble yours. Take the time to search for "window wrapper", "static wndproc", etc.
    Last edited by Dante Shamest; 03-03-2005 at 11:18 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Superclassed edit control; custom notifications
    By Boksha in forum Windows Programming
    Replies: 2
    Last Post: 12-16-2006, 03:21 PM
  2. Button handler
    By Nephiroth in forum Windows Programming
    Replies: 8
    Last Post: 03-12-2006, 06:23 AM
  3. Custom control information
    By Mithoric in forum Windows Programming
    Replies: 6
    Last Post: 03-02-2004, 06:52 AM
  4. Custom Tab Control
    By PrivatePanic in forum Windows Programming
    Replies: 8
    Last Post: 07-19-2002, 01:23 PM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM