在非主线程上创建窗口、执行消息循环,无法得到WM_CLOSE消息 本帖最后由 liuchao35758600 于 2013-09-14 19:10:19 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。 唯一的消息循环是在新建的线程上跑的,窗口也是在这个线程上调用 CreateWindow 函数创建的。显示窗口和调整窗口位置、尺寸及样式,是在主线程上执行的。 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。在子线程上创建的窗口是无法得到Window消息的,必须创建线程的消息循环,然后在子线程上创建窗口 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧? 就在GetMessage函数获取到消息后打印它的,与该函数处于同一线程。代码类似于这样:if( GetMessage( &msg, hwnd, 0, 0 ) ) { printf("message: %u\n", msg.message); //......} 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧?不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧?不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做while(true){ Sleep(100); // ms if (bQuit) // 控制从线程结束的全局变量 { _endthread(); } 要实现的功能} 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧?不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做while(true){ Sleep(100); // ms if (bQuit) // 控制从线程结束的全局变量 { _endthread(); } 要实现的功能}但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收? 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧?不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做while(true){ Sleep(100); // ms if (bQuit) // 控制从线程结束的全局变量 { _endthread(); } 要实现的功能}但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收?你能把你界面线程启动的代码贴一下么?我现在想不出来你是怎么实现的。 在主线程的close函数中对窗口发送WM_CLOSE消息试试SendMessage(pSubWnd->m_hWnd, WM_CLOSE, 0, 0); 主窗口是主线程创建,子窗口是子线程创建。void//主窗口结束函数MainDialog::OnClose(){ CloseSubWnd(&m_dlgToolbox); CloseSubWnd(&m_dlgAutoDiagnose); SetMsgHandled(FALSE); EndDialog(IDCANCEL);}template<typename SubWndType>BOOL MainDialog::CloseSubWnd(SubWndType* pSubWnd){ if(pSubWnd->m_hWnd) { ::SendMessage(pSubWnd->m_hWnd, WM_CLOSE, 0, 0); } return TRUE;} 还有在子窗口中要写WM_CLOSE和WM_DISTORY消息响应(十分重要)template<typename SubWndType>LRESULT CSubWndCommon<SubWndType>::OnClose(){ DestroyWindow(m_pSubWnd->m_hWnd); return S_OK;}template<typename SubWndType>LRESULT CSubWndCommon<SubWndType>::OnDestroy(){ PostQuitMessage(0); return S_OK;} 这个阻塞函数和GetMessage函数类似,用于在循环里阻塞获取数据,让程序处理。目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道你新建的线程是看不到的程序唯一的一个窗口也是在新线程上创建的。我好像明白一点了,你这个不是MFC工程吧?不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做while(true){ Sleep(100); // ms if (bQuit) // 控制从线程结束的全局变量 { _endthread(); } 要实现的功能}但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收?你能把你界面线程启动的代码贴一下么?我现在想不出来你是怎么实现的。以下是部分代码:#include <LCUI_Build.h>#include LC_LCUI_H#ifdef LCUI_VIDEO_DRIVER_WIN32#include LC_GRAPH_H#include LC_INPUT_H#include LC_CURSOR_H#include LC_DISPLAY_H#include LC_WIDGET_H#include <Windows.h>#include "resource.h"static HWND current_hwnd = NULL;static int pixel_mem_len = 0;static unsigned char *pixel_mem = NULL;static HDC hdc_client, hdc_framebuffer;static HBITMAP client_bitmap;static HINSTANCE win32_hInstance = NULL, dll_hInstance = NULL;static LCUI_Mutex screen_mutex;static LCUI_Thread th_win32;static LCUI_Sleeper win32_init_sleeper;static LCUI_BOOL win32_init_error = TRUE;LCUI_API void Win32_LCUI_Init( HINSTANCE hInstance ){ win32_hInstance = hInstance;}static LRESULT CALLBACK Win32_LCUI_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; LCUI_Rect area; switch (message) { case WM_KEYDOWN: LCUIKeyboard_HitKey( wParam ); return 0; case WM_KEYUP: LCUIKeyboard_FreeKey( wParam ); return 0; case WM_RBUTTONDOWN: LCUIMouse_ButtonDown( LCUIKEY_RIGHTBUTTON ); return 0; case WM_RBUTTONUP: LCUIMouse_ButtonUp( LCUIKEY_RIGHTBUTTON ); return 0; case WM_LBUTTONDOWN: LCUIMouse_ButtonDown( LCUIKEY_LEFTBUTTON ); return 0; case WM_LBUTTONUP: LCUIMouse_ButtonUp( LCUIKEY_LEFTBUTTON ); return 0; case WM_PAINT: BeginPaint( hwnd, &ps ); /* 获取区域坐标及尺寸 */ area.x = ps.rcPaint.left; area.y = ps.rcPaint.top; area.width = ps.rcPaint.right - area.x; area.height = ps.rcPaint.bottom - area.y; /* 记录该无效区域 */ LCUIScreen_InvalidArea( area ); EndPaint( hwnd, &ps ); return 0; case WM_DESTROY: PostQuitMessage(0); LCUI_Quit(); return 0; default:break; } return DefWindowProc (hwnd, message, wParam, lParam) ;}LCUI_API HWND Win32_GetSelfHWND( void ){ return current_hwnd;}LCUI_API void Win32_SetSelfHWND( HWND hwnd ){ current_hwnd = hwnd;}/** 动态库的入口函数 */BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } dll_hInstance = hModule; return TRUE;}static int Win32_ScreenInit(void){ WNDCLASS wndclass; TCHAR szAppName[] = TEXT ("LCUI OutPut"); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = Win32_LCUI_WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = win32_hInstance; /* 载入动态库里的图标 */ wndclass.hIcon = LoadIcon( dll_hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON) ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return -1; } /* 创建窗口 */ current_hwnd = CreateWindow ( szAppName, TEXT ("LCUI"), WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, win32_hInstance, NULL); return 0;}/** Win32的消息循环线程 */static void LCUI_Win32_Thread( void *arg ){ MSG msg; if( Win32_ScreenInit() == -1 ) { /* 设置标志为TRUE,表示初始化失败 */ win32_init_error = TRUE; /* 打断处于睡眠状态的线程的睡眠 */ LCUISleeper_BreakSleep( &win32_init_sleeper ); LCUIThread_Exit(NULL); return; } /* 设置标志为FALSE,表示初始化成功 */ win32_init_error = FALSE; /* 隐藏windows的鼠标游标 */ ShowCursor( FALSE ); LCUISleeper_BreakSleep( &win32_init_sleeper ); while( LCUI_Sys.state == ACTIVE ) { /* 获取消息 */ if( GetMessage( &msg, Win32_GetSelfHWND(), 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } LCUIThread_Exit(NULL);}/** 初始化屏幕 */LCUI_API int LCUIScreen_Init( int w, int h, int mode ){ LCUI_Widget *root_widget; LCUI_Screen screen_info; /* 初始化屏幕互斥锁 */ LCUIMutex_Init( &screen_mutex ); LCUISleeper_Create( &win32_init_sleeper ); /* 创建线程 */ LCUIThread_Create( &th_win32, LCUI_Win32_Thread, NULL ); /* 进行睡眠,最长时间为5秒 */ LCUISleeper_StartSleep( &win32_init_sleeper, 5000 ); /* 若初始化出现错误 */ if( win32_init_error ) { return -1; } /* 准备屏幕相关信息 */ screen_info.bits = 32; screen_info.mode = mode; strcpy( screen_info.dev_name, "win32 GDI" ); /* 设置屏幕信息 */ LCUIScreen_SetInfo( &screen_info ); /* 设置图形输出模式 */ LCUIScreen_SetMode( w, h, mode ); w = GetSystemMetrics(SM_CXSCREEN); h = GetSystemMetrics(SM_CYSCREEN); pixel_mem_len = w*h*4; /* 分配内存,储存像素数据 */ pixel_mem = (uchar_t*)malloc( pixel_mem_len ); /* 获取客户区的DC */ hdc_client = GetDC( current_hwnd ); /* 为帧缓冲创建一个DC */ hdc_framebuffer = CreateCompatibleDC( hdc_client ); /* 为客户区创建一个Bitmap */ client_bitmap = CreateCompatibleBitmap( hdc_client, w, h ); /* 为帧缓冲的DC选择client_bitmap作为对象 */ SelectObject( hdc_framebuffer, client_bitmap ); root_widget = RootWidget_GetSelf(); Widget_Resize( root_widget, screen_info.size ); Widget_SetBackgroundColor( root_widget, RGB(255,255,255) ); Widget_SetBackgroundTransparent( root_widget, FALSE ); Widget_Show( root_widget ); /* 显示窗口 */ ShowWindow( current_hwnd, SW_SHOWNORMAL ); UpdateWindow( current_hwnd ); return 0;}// 省略剩余代码 楼主说的是在子线程创建的窗口?那主线程有木有窗口呢?楼主可以看一下这个:http://blog.csdn.net/norains/article/details/2023957 请教个Inno setup安装包制作工具的问题 为什么BCG界面库做的框架在Win7下无效? 有人作过IEC104规约通信吗?有问题想问: CFormView 控件位置 排列 怎么创建一个异步的ActiveX控件? 管道(pipe)的读写是否支持多线程? 如何在编辑框中输入一个字符,却显示另一个字符? 求助!高手请进! 能不能在VC中调用Dephi的DLL啊。。。 NT下串口通信的问题:关于错误控制 大侠急救,出现了大问题。。。。 本人捣鼓的CChart最新版2.5.1.2版发布
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
显示窗口和调整窗口位置、尺寸及样式,是在主线程上执行的。
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。在子线程上创建的窗口是无法得到Window消息的,必须创建线程的消息循环,然后在子线程上创建窗口
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
代码类似于这样:if( GetMessage( &msg, hwnd, 0, 0 ) ) {
printf("message: %u\n", msg.message);
//......
}
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。
还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做
while(true)
{
Sleep(100); // ms
if (bQuit) // 控制从线程结束的全局变量
{
_endthread();
}
要实现的功能
}
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。
还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做
while(true)
{
Sleep(100); // ms
if (bQuit) // 控制从线程结束的全局变量
{
_endthread();
}
要实现的功能
}
但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收?
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。
还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做
while(true)
{
Sleep(100); // ms
if (bQuit) // 控制从线程结束的全局变量
{
_endthread();
}
要实现的功能
}
但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收?
你能把你界面线程启动的代码贴一下么?我现在想不出来你是怎么实现的。
SendMessage(pSubWnd->m_hWnd, WM_CLOSE, 0, 0);
MainDialog::OnClose()
{
CloseSubWnd(&m_dlgToolbox);
CloseSubWnd(&m_dlgAutoDiagnose); SetMsgHandled(FALSE);
EndDialog(IDCANCEL);
}template<typename SubWndType>
BOOL
MainDialog::CloseSubWnd(SubWndType* pSubWnd)
{
if(pSubWnd->m_hWnd)
{
::SendMessage(pSubWnd->m_hWnd, WM_CLOSE, 0, 0);
} return TRUE;
}
template<typename SubWndType>
LRESULT
CSubWndCommon<SubWndType>::OnClose()
{
DestroyWindow(m_pSubWnd->m_hWnd);
return S_OK;
}template<typename SubWndType>
LRESULT
CSubWndCommon<SubWndType>::OnDestroy()
{
PostQuitMessage(0);
return S_OK;
}
目前有个解决方案,将那个阻塞函数放到线程上执行,消息循环还是放在主线程上执行。但我想知道这个问题的原因。
消息的投递有4个参数,第一个是窗口句柄,也就是说,你点击程序界面的关闭按钮
此时接收该消息的窗口是主线程创建的,因此只有主线程的消息循环处理能知道
你新建的线程是看不到的
程序唯一的一个窗口也是在新线程上创建的。
我好像明白一点了,你这个不是MFC工程吧?
不是MFC工程,用的工具是VisualStudio2012,选择的是“win32 项目”,应用程序类型为:“windows 应用程序”。
还真没试验过这种用法。你在子线程中也可以做阻塞的,只要你这么做
while(true)
{
Sleep(100); // ms
if (bQuit) // 控制从线程结束的全局变量
{
_endthread();
}
要实现的功能
}
但问题是,我问的不是如何在子线程中做阻塞,而是子线程上的消息循环为何能不能接收到WM_QUIT、WM_CLOSE和WM_DESTROY这三个消息、其它消息(鼠标移动、鼠标点击、按键等)却能接收?
你能把你界面线程启动的代码贴一下么?我现在想不出来你是怎么实现的。
以下是部分代码:
#include <LCUI_Build.h>
#include LC_LCUI_H#ifdef LCUI_VIDEO_DRIVER_WIN32#include LC_GRAPH_H
#include LC_INPUT_H
#include LC_CURSOR_H
#include LC_DISPLAY_H
#include LC_WIDGET_H
#include <Windows.h>
#include "resource.h"static HWND current_hwnd = NULL;
static int pixel_mem_len = 0;
static unsigned char *pixel_mem = NULL;
static HDC hdc_client, hdc_framebuffer;
static HBITMAP client_bitmap;
static HINSTANCE win32_hInstance = NULL, dll_hInstance = NULL;
static LCUI_Mutex screen_mutex;
static LCUI_Thread th_win32;
static LCUI_Sleeper win32_init_sleeper;
static LCUI_BOOL win32_init_error = TRUE;LCUI_API void Win32_LCUI_Init( HINSTANCE hInstance )
{
win32_hInstance = hInstance;
}static LRESULT CALLBACK Win32_LCUI_WndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam )
{
PAINTSTRUCT ps;
LCUI_Rect area; switch (message) {
case WM_KEYDOWN:
LCUIKeyboard_HitKey( wParam );
return 0;
case WM_KEYUP:
LCUIKeyboard_FreeKey( wParam );
return 0;
case WM_RBUTTONDOWN:
LCUIMouse_ButtonDown( LCUIKEY_RIGHTBUTTON );
return 0;
case WM_RBUTTONUP:
LCUIMouse_ButtonUp( LCUIKEY_RIGHTBUTTON );
return 0;
case WM_LBUTTONDOWN:
LCUIMouse_ButtonDown( LCUIKEY_LEFTBUTTON );
return 0;
case WM_LBUTTONUP:
LCUIMouse_ButtonUp( LCUIKEY_LEFTBUTTON );
return 0;
case WM_PAINT:
BeginPaint( hwnd, &ps );
/* 获取区域坐标及尺寸 */
area.x = ps.rcPaint.left;
area.y = ps.rcPaint.top;
area.width = ps.rcPaint.right - area.x;
area.height = ps.rcPaint.bottom - area.y;
/* 记录该无效区域 */
LCUIScreen_InvalidArea( area );
EndPaint( hwnd, &ps );
return 0;
case WM_DESTROY:
PostQuitMessage(0);
LCUI_Quit();
return 0;
default:break;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}LCUI_API HWND Win32_GetSelfHWND( void )
{
return current_hwnd;
}LCUI_API void Win32_SetSelfHWND( HWND hwnd )
{
current_hwnd = hwnd;
}/** 动态库的入口函数 */
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
dll_hInstance = hModule;
return TRUE;
}static int Win32_ScreenInit(void)
{
WNDCLASS wndclass;
TCHAR szAppName[] = TEXT ("LCUI OutPut"); wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = Win32_LCUI_WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = win32_hInstance;
/* 载入动态库里的图标 */
wndclass.hIcon = LoadIcon( dll_hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON) );
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass (&wndclass)) {
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return -1;
}
/* 创建窗口 */
current_hwnd = CreateWindow (
szAppName, TEXT ("LCUI"),
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0,
NULL, NULL, win32_hInstance, NULL);
return 0;
}/** Win32的消息循环线程 */
static void LCUI_Win32_Thread( void *arg )
{
MSG msg;
if( Win32_ScreenInit() == -1 ) {
/* 设置标志为TRUE,表示初始化失败 */
win32_init_error = TRUE;
/* 打断处于睡眠状态的线程的睡眠 */
LCUISleeper_BreakSleep( &win32_init_sleeper );
LCUIThread_Exit(NULL);
return;
}
/* 设置标志为FALSE,表示初始化成功 */
win32_init_error = FALSE;
/* 隐藏windows的鼠标游标 */
ShowCursor( FALSE );
LCUISleeper_BreakSleep( &win32_init_sleeper );
while( LCUI_Sys.state == ACTIVE ) {
/* 获取消息 */
if( GetMessage( &msg, Win32_GetSelfHWND(), 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
LCUIThread_Exit(NULL);
}/** 初始化屏幕 */
LCUI_API int LCUIScreen_Init( int w, int h, int mode )
{
LCUI_Widget *root_widget;
LCUI_Screen screen_info; /* 初始化屏幕互斥锁 */
LCUIMutex_Init( &screen_mutex );
LCUISleeper_Create( &win32_init_sleeper );
/* 创建线程 */
LCUIThread_Create( &th_win32, LCUI_Win32_Thread, NULL );
/* 进行睡眠,最长时间为5秒 */
LCUISleeper_StartSleep( &win32_init_sleeper, 5000 );
/* 若初始化出现错误 */
if( win32_init_error ) {
return -1;
}
/* 准备屏幕相关信息 */
screen_info.bits = 32;
screen_info.mode = mode;
strcpy( screen_info.dev_name, "win32 GDI" );
/* 设置屏幕信息 */
LCUIScreen_SetInfo( &screen_info );
/* 设置图形输出模式 */
LCUIScreen_SetMode( w, h, mode ); w = GetSystemMetrics(SM_CXSCREEN);
h = GetSystemMetrics(SM_CYSCREEN);
pixel_mem_len = w*h*4; /* 分配内存,储存像素数据 */
pixel_mem = (uchar_t*)malloc( pixel_mem_len );
/* 获取客户区的DC */
hdc_client = GetDC( current_hwnd );
/* 为帧缓冲创建一个DC */
hdc_framebuffer = CreateCompatibleDC( hdc_client );
/* 为客户区创建一个Bitmap */
client_bitmap = CreateCompatibleBitmap( hdc_client, w, h );
/* 为帧缓冲的DC选择client_bitmap作为对象 */
SelectObject( hdc_framebuffer, client_bitmap );
root_widget = RootWidget_GetSelf();
Widget_Resize( root_widget, screen_info.size );
Widget_SetBackgroundColor( root_widget, RGB(255,255,255) );
Widget_SetBackgroundTransparent( root_widget, FALSE );
Widget_Show( root_widget );
/* 显示窗口 */
ShowWindow( current_hwnd, SW_SHOWNORMAL );
UpdateWindow( current_hwnd );
return 0;
}// 省略剩余代码
楼主可以看一下这个:
http://blog.csdn.net/norains/article/details/2023957