-
October 6th, 2011, 08:14 AM
#1
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.
-
October 6th, 2011, 08:16 AM
#2
Re: WinApi GUIClass with 2 WindowProc Problem
It stucks on GetMessage() function on mainWindow procedure
-
October 6th, 2011, 09:03 PM
#3
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
-
October 7th, 2011, 03:22 AM
#4
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->hInstance, wsi->WindowTitle); //guiManager.ShowGUIWindow(); guiManager.ProcessGUIMessages(); delete wsi; _endthread(); }
void NodeManager::CreateGUIWindow(HINSTANCE hInstance, int nCmdShow, TCHAR *WindowTitle) { winStructInfo *wsi = new winStructInfo(); wsi->hInstance = hInstance; wsi->nCmdShow = nCmdShow; wsi->WindowTitle = WindowTitle; _beginthread(NodeManager::CreateGUIThread, 0, wsi); }
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|