CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Oct 2011
    Posts
    3

    WinApi GUIClass with 2 WindowProc Problem

    Hi, I am making a node editor,
    The editing interface (GUI Window) is launched in a separated thread and its wrapped in a class.
    The main window it self is working good, but if I add my custom window for nodes the main window stucks on GetMessage() function.

    The window procedure for both MainWindow and NodeWindow is in the same class, I'm not sure what is the problem, because I've made some tests without classes and threads and worked without poblems.

    Here is the code for the GUIManager class (In which is the MainWindow/NodeWindow proc)


    GUIManager.h
    Code:
    #pragma once
    
    #include "GlobalIncludes.h"
    
    #define CUST_BUTTON_CLASS_NAME  _T("NodeWindowClass")
    
    class GUIManager
    {
    private:
    	HWND winHandle;
    	ULONG_PTR gdiplusToken;
    	BOOL RunGUIWindow;
    
    	BOOL RegisterGUIWindow(HINSTANCE hInstance, TCHAR *ClassName) ;
    	static LRESULT CALLBACK stWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    	LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    
    
    	static LRESULT CALLBACK stNodeProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    	LRESULT CALLBACK NodeProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    	void Node_OnPaint(HWND hwnd);
    	
    public:
    	GUIManager(void);
    	~GUIManager(void);
    
    	BOOL CreateGUIWindow(HINSTANCE hInstance, TCHAR *Title);
    	void ProcessGUIMessages(void);
    	void ShowGUIWindow(void);
    	void HideGUIWindow(void);
    	void KillGUIWindow(void);
    	HWND GetHandle(void) {return winHandle;}
    	BOOL IsRunning(void) {return RunGUIWindow;}
    
    	BOOL RegisterNodeWindow(void);
    	HWND CreateNodeWindow(int x, int y);
    };

    GUIManager.cpp
    Code:
    #include "GUIManager.h"
    
    
    
    BOOL GUIManager::RegisterGUIWindow(HINSTANCE hInstance, TCHAR *ClassName) 
    {
    	WNDCLASS wc = { };
    
    	wc.lpfnWndProc   = GUIManager::stWindowProc;
        wc.hInstance     = hInstance;
        wc.lpszClassName = ClassName;
    	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground  = (HBRUSH)GetStockObject(GRAY_BRUSH);
    	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    
    	return RegisterClass(&wc);
    }
    
    BOOL GUIManager::CreateGUIWindow(HINSTANCE hInstance, TCHAR *Title) 
    {
    	TCHAR ClassName[] = _T("GUIManager");
    
    	RegisterGUIWindow(hInstance, ClassName);
    
    	winHandle = CreateWindowEx(
    		0,															// Optional window styles.
            ClassName,													// Window class
            Title,														// Window text
            WS_OVERLAPPEDWINDOW |  WS_HSCROLL | WS_VSCROLL,				// Window style
    
    																	// Size and position
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    
            NULL,       // Parent window    
            NULL,       // Menu
            hInstance,  // Instance handle
            (void*)this        // Additional application data
            );
    
        if (winHandle == NULL)
        {
            return 0;
        }
    
    	
    	return 1;
        //ShowWindow(winHandle, SW_SHOW);
    }
    
    void GUIManager::ProcessGUIMessages() 
    {
    	RunGUIWindow = true;
    	// Run the message loop.
        MSG msg = { };
        while (GetMessage(&msg, NULL, 0, 0) && RunGUIWindow)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    GUIManager::GUIManager()
    {
    	GdiplusStartupInput gdiplusStartupInput;
       
    	// Initialize GDI+.
    	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    }
    
    GUIManager::~GUIManager(void)
    {
    	if (winHandle && IsWindow(winHandle)) {
    		DestroyWindow(winHandle);
    	}
    	GdiplusShutdown(gdiplusToken);
    }
    
    LRESULT CALLBACK GUIManager::stWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	GUIManager *GUIApp;
    	if(uMsg == WM_CREATE)
    	{
    		GUIApp = (GUIManager*)((LPCREATESTRUCT)lParam)->lpCreateParams;
    		SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)GUIApp);
    	}
    	else
    		GUIApp = (GUIManager*)GetWindowLongPtr(hWnd, GWL_USERDATA);
    
    	if(GUIApp == NULL)
    		return DefWindowProc(hWnd, uMsg, wParam, lParam);
    	return GUIApp->WindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    
    LRESULT CALLBACK GUIManager::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch (uMsg)
        {
    
    	case WM_DESTROY:
    		RunGUIWindow = false;
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    void GUIManager::ShowGUIWindow(void) 
    {
    	ShowWindow(winHandle, SW_SHOW);
    }
    
    void GUIManager::HideGUIWindow(void) 
    {
    	ShowWindow(winHandle, SW_HIDE);
    }
    
    void GUIManager::KillGUIWindow(void) 
    {
    	DestroyWindow(winHandle);
    }
    
    
    //NODES
    
    BOOL GUIManager::RegisterNodeWindow()
    {
    	WNDCLASSEX wc;
        ATOM atom;
    	
        if (GetClassInfoEx(NULL, CUST_BUTTON_CLASS_NAME, &wc))
            return 0;        /*  Already registered  */
     
        wc.cbClsExtra = 0;
    
        wc.cbSize = sizeof(WNDCLASSEX);
    
        wc.cbWndExtra = 0;
    
        wc.hbrBackground = (HBRUSH)NULL;//(HBRUSH)(COLOR_WINDOW + 1);
    
    	wc.hCursor = LoadCursor(NULL, IDC_HAND);
    
        wc.hIcon = NULL;
    
        wc.hIconSm = NULL;
    
        wc.hInstance = NULL; 
    
    	wc.lpfnWndProc = GUIManager::stNodeProc;
    
        wc.lpszClassName = CUST_BUTTON_CLASS_NAME;
    
        wc.lpszMenuName = NULL;
    
        wc.style = CS_GLOBALCLASS;
    
        atom = RegisterClassEx(&wc);
    
    	return 1;
    }
    
    HWND GUIManager::CreateNodeWindow(int x, int y)
    {
    	HWND hwndCtrl;
    
        hwndCtrl = CreateWindowEx(
    
    				 0, // give it a standard border //WS_EX_CLIENTEDGE 
    
                     CUST_BUTTON_CLASS_NAME,
    
                     _T("A custom control"), //txt, //
    
    				 WS_VISIBLE | WS_CHILD |  WS_OVERLAPPED,
    
                     x, y, 200, 100,
    
                     winHandle,
    
                     NULL, GetModuleHandle(0), (void*)this
    
                   );
    
    	HRGN roundRGN = CreateRoundRectRgn(0, 0, 200, 100, 10, 10);
    	SetWindowRgn(hwndCtrl, roundRGN, TRUE);
    
        return hwndCtrl;
    }
    
    LRESULT CALLBACK GUIManager::stNodeProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	GUIManager *GUIApp;
    	if(uMsg == WM_CREATE)
    	{
    		GUIApp = (GUIManager*)((LPCREATESTRUCT)lParam)->lpCreateParams;
    		SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)GUIApp);
    	}
    	else
    		GUIApp = (GUIManager*)GetWindowLongPtr(hWnd, GWL_USERDATA);
    
    	if(GUIApp == NULL)
    		return DefWindowProc(hWnd, uMsg, wParam, lParam);
    	return GUIApp->NodeProc(hWnd, uMsg, wParam, lParam);
    }
    
    
    LRESULT CALLBACK GUIManager::NodeProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch (uMsg)
        {
    	HANDLE_MSG (hWnd, WM_PAINT, Node_OnPaint);
    	case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    void GUIManager::Node_OnPaint(HWND hWnd) 
    {
    	PAINTSTRUCT ps;
                HDC hDC;
                RECT rect;
                BOOL bSuccess;
    
                hDC = BeginPaint(hWnd, &ps);
    
                bSuccess = GetClientRect(hWnd, &rect);
    
    			RectF grRect;
    			grRect.X = 0;
    			grRect.Y = 0;
    			grRect.Width = rect.right - rect.left;
    			grRect.Height = rect.bottom - rect.top;
    
    			Graphics graphics(hDC);
    			LinearGradientBrush linGrBrush(
    			Point(0, 0),
    			Point(0, grRect.Height),
    			Color(61, 132, 155),   // opaque red
    			Color(57, 159, 204));  // opaque blue
    
    			Region a(RectF(grRect.X, grRect.Y, grRect.Width, grRect.Height));
    			a.Xor(RectF(0, 30, grRect.Width, grRect.Height - 40));
    			graphics.FillRegion(&linGrBrush, &a);
    			//graphics.FillRectangle(&linGrBrush, grRect); 
    
    			SolidBrush middle(Color(50,50,150));
    
    			graphics.FillRectangle(&middle, Rect(0, 30, grRect.Width, grRect.Height - 40));
    
    
    			//TEXT
    
    
    			WCHAR        szText[200];
    
    
    			GetWindowTextW(hWnd, szText, sizeof(szText));
    
       
    
    
    
    				// Find out how big the text will be
    			SIZE sz;
    			GetTextExtentPoint32W(hDC, szText, lstrlenW(szText), &sz);
    
    
    
        // Center the text
    
        int x = (rect.right  - sz.cx) / 2;
    
        
    	rect.top = 5;
    	rect.left = 5;
    	rect.right = grRect.Width - 10;
    	rect.bottom = 20;
    
    	
    	FontFamily  fontFamily(L"Times New Roman");
    	Font        font(&fontFamily, 14, FontStyleBold, UnitPixel);
    	PointF      pointF(x, 5.f);
    	SolidBrush  solidBrush(Color(255, 255, 255));
    	StringFormat sf;
    	sf.SetAlignment(StringAlignment::StringAlignmentCenter);
    
    	graphics.DrawString(szText, -1, &font, RectF(5, 5, grRect.Width-10, 20), &sf, &solidBrush);
    	
        bSuccess = EndPaint(hWnd, &ps);
    }
    Last edited by spider853; October 6th, 2011 at 09:22 AM.

  2. #2
    Join Date
    Oct 2011
    Posts
    3

    Re: WinApi GUIClass with 2 WindowProc Problem

    It stucks on GetMessage() function on mainWindow procedure

  3. #3
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: WinApi GUIClass with 2 WindowProc Problem

    Generally speaking, you should not create windows in different threads. The general recommendation is to use the main thread (and only the main thread) responsible for all GUI work. Worker threads can be created and run for the purposes of executing non-GUI related work, and can PostMessage custom messages to the windows of the main thread, so as to display the results of the work.

    There are exceptions to this rule, but it's not clear from your post whether there is a good reason for you to create a window from a secondary thread.

    Mike

  4. #4
    Join Date
    Oct 2011
    Posts
    3

    Re: WinApi GUIClass with 2 WindowProc Problem

    The problem is that this GUI is for a 3ds max plugin and I cannot process the message in the main thread.
    That's why I start this class in another thread like this:

    PHP Code:
    void NodeManager::CreateGUIThread(void *param)
    {
        
    winStructInfo *wsi = (winStructInfo*)param;
        
    guiManager.CreateGUIWindow(wsi->hInstancewsi->WindowTitle);
        
    //guiManager.ShowGUIWindow();
        
    guiManager.ProcessGUIMessages();
        
        
    delete wsi;
        
    _endthread();
    }

    void NodeManager::CreateGUIWindow(HINSTANCE hInstanceint nCmdShowTCHAR *WindowTitle)
    {
        
    winStructInfo *wsi = new winStructInfo();
        
    wsi->hInstance hInstance;
        
    wsi->nCmdShow nCmdShow;
        
    wsi->WindowTitle WindowTitle;
        
    _beginthread(NodeManager::CreateGUIThread0wsi);


Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured