完整,干净的WINAPI窗口创建

本文介绍了一个简单的Windows程序示例,通过创建窗口、响应消息等步骤展示了基本的Win32编程流程。涉及窗口类的设计与注册、窗口创建及消息处理。

像C学习的第一个程序一样“hello world”级别的基础WIN32程序。




// WindowsApp.cpp


#include <windows.h>        // 包含windows头文件
#include <stdio.h>
#define  BUFFER_LENGTH  50  // buffer长度


// 自定义函数声明
BOOL DesignClass(HINSTANCE hInstance);  // 设计并注册一个新窗口类
BOOL CreateWnd(HINSTANCE hInstance);    // 创建新窗口并显示和刷新新窗口


// 窗口过程函数声明
LRESULT CALLBACK SampleWindowProc(
  HWND hwnd,      // 窗口句柄
  UINT uMsg,      // 消息类型
  WPARAM wParam,  // 消息的附加信息
  LPARAM lParam   // 消息的附加信息
);


// 定义WinMain函数
int WINAPI WinMain(
  HINSTANCE hInstance,      // 当前实例句柄
  HINSTANCE hPrevInstance,  // 前一实例句柄
  LPSTR lpCmdLine,          // 指向命令行参数的指针
  int nCmdShow              // 窗口的显示方式
)
{
// 设计并注册一个新窗口类
if ( !DesignClass(hInstance) )
{
MessageBox( NULL, "设计或者注册新窗口类失败!", "Windows窗口应用程序", 0 );
return FALSE;
}


// 创建新窗口并显示和刷新新窗口
if ( !CreateWnd(hInstance) )
{
MessageBox( NULL, "创建新窗口失败!", "Windows窗口应用程序", 0 );
return FALSE;
}


// 为应用程序添加消息循环
MSG msg;  // 定义消息结构体
// 消息循环体
while ( GetMessage( &msg, NULL, 0, 0) )  // 从消息队列中获取消息
{
TranslateMessage(&msg);  // 投递消息到消息队列
DispatchMessage(&msg);   // 分派消息到窗口过程
}


return msg.wParam;
}


// 设计并注册一个新窗口类
BOOL DesignClass(HINSTANCE hInstance)
{
// 设计一个新窗口类
WNDCLASS wndClass;  // 定义窗口类结构体
wndClass.style       = CS_HREDRAW | CS_VREDRAW;  // 窗口样式
wndClass.lpfnWndProc = SampleWindowProc;         // 窗口过程的函数指针
wndClass.cbClsExtra  = 0;                        // 在窗口类结构之后分配的附加字节数
wndClass.cbWndExtra  = 0;                        // 在窗口实例之后分配的附加字节数
wndClass.hInstance   = hInstance;                // 窗口过程所属的实例
wndClass.hIcon       = LoadIcon( NULL, IDI_APPLICATION );     // 窗口图标
wndClass.hCursor     = LoadCursor( NULL, IDC_ARROW );         // 窗口光标
wndClass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);  // 窗口背景画刷
wndClass.lpszMenuName  = NULL;                                // 窗口无缺省菜单
wndClass.lpszClassName = "WindowsApp";                        // 窗口类名称


// 注册新窗口类
return RegisterClass(&wndClass);
}


// 创建新窗口并显示和刷新新窗口
BOOL CreateWnd(HINSTANCE hInstance)
{
// 创建新窗口
HWND hWnd;  // 定义变量用于保存创建窗口成功后返回的句柄
hWnd = CreateWindow("WindowsApp",  // 窗口类名称
"Windows窗口应用程序",         // 窗口标题栏名称
WS_OVERLAPPEDWINDOW,           // 窗口样式
CW_USEDEFAULT,                 // 窗口水平位置
CW_USEDEFAULT,                 // 窗口垂直位置
CW_USEDEFAULT,                 // 窗口宽度
CW_USEDEFAULT,                 // 窗口高度
NULL,                          // 父窗口句柄
NULL,                          // 窗口菜单句柄
hInstance,                     // 窗口实例句柄
NULL );                        // 窗口创建参数


if ( !hWnd )  // 新窗口创建失败
{
return FALSE;
}
else          // 新窗口创建成功
{
// 显示新窗口
ShowWindow( hWnd, SW_SHOWNORMAL);


// 刷新新窗口
UpdateWindow(hWnd);


return TRUE;
}
}


// 定义窗口过程函数
LRESULT CALLBACK SampleWindowProc(
  HWND hwnd,      // 窗口句柄
  UINT uMsg,      // 消息类型
  WPARAM wParam,  // 消息的附加信息
  LPARAM lParam   // 消息的附加信息
)
{
// 处理接收的消息
switch ( uMsg )
{
case WM_CHAR:         // 键盘字符消息
char cBuf[BUFFER_LENGTH];
sprintf( cBuf, "您按下了键盘%c", wParam );  // 格式化消息参数
MessageBox( hwnd, cBuf, "Windows窗口应用程序", 0 );
break;


case WM_LBUTTONDOWN:  // 鼠标左键消息
MessageBox( hwnd, "您单击了鼠标左键,将在窗口客户区左上角绘制一个矩形", "Windows窗口应用程序", 0 );
HDC hdc;
hdc = GetDC( hwnd );              // 获得窗口DC
Rectangle( hdc, 0, 0, 200, 100);  // 绘制矩形
ReleaseDC( hwnd, hdc );
break;


case WM_RBUTTONDOWN:  // 鼠标右键消息
MessageBox( hwnd, "您单击了鼠标右键,将擦除单击鼠标左键时绘制的矩形", "Windows窗口应用程序", 0 );
RECT Rect;
Rect.left   = 0;
Rect.top    = 0;
Rect.right  = 200;
Rect.bottom = 100;
InvalidateRect( hwnd, &Rect, TRUE );  // 使得矩形区域失效
break;


case WM_PAINT:        // 重绘窗口
RECT rect;
GetClientRect( hwnd, &rect );          // 获取窗口客户区矩形区域
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint( hwnd, &ps );        // 获得窗口DC
SetTextColor( hDC, RGB(255, 0, 0) );  // 设置字体颜色
TextOut( hDC, 
(rect.right-rect.left)/3, 
(rect.bottom-rect.top)/6, 
"程序名称:简单Windows窗口应用程序", 
strlen("程序名称:简单Windows窗口应用程序") );
TextOut( hDC, 
(rect.right-rect.left)/3, 
(rect.bottom-rect.top)/3, 
"系统平台:WindowsXP SP2", 
strlen("系统平台:WindowsXP SP2") );
TextOut( hDC, 
(rect.right-rect.left)/3, 
(rect.bottom-rect.top)/2, 
"开发工具:Microsoft Visual c++ 6.0", 
strlen("开发工具:Microsoft Visual c++ 6.0") );
EndPaint( hwnd, &ps );
break;


case WM_CLOSE:        // 关闭窗口
if ( IDYES == MessageBox( hwnd, "是否真的要关闭窗口", "Windows窗口应用程序", MB_YESNO) )
{
DestroyWindow( hwnd );  // 销毁窗口
}
break;


case WM_DESTROY:      // 销毁窗口
PostQuitMessage( 0 );
break;


default:
break;
}


return DefWindowProc( hwnd, uMsg, wParam, lParam );
}

### 使用 Golang 调用 WinAPI 创建桌面窗口 以下是通过 Golang 和 `syscall` 包调用 Windows API 来创建一个简单的桌面窗口的示例代码: ```go package main import ( "fmt" "syscall" "unsafe" ) var ( user32 = syscall.NewLazyDLL("user32.dll") kernel32 = syscall.NewLazyDLL("kernel32.dll") getModuleHandle = kernel32.NewProc("GetModuleHandleW") createWindowEx = user32.NewProc("CreateWindowExW") showWindow = user32.NewProc("ShowWindow") updateWindow = user32.NewProc("UpdateWindow") messageBox = user32.NewProc("MessageBoxW") GetMessage = user32.NewProc("GetMessageW") translateMessage = user32.NewProc("TranslateMessage") dispatchMessage = user32.NewProc("DispatchMessageW") postQuitMessage = user32.NewProc("PostQuitMessage") ) const ( CW_USEDEFAULT uintptr = 0x80000000 SW_SHOW = 5 IDOK = 1 ) func main() { var hwnd uintptr var msg struct { Hwnd uintptr Message uint32 WParam uintptr LParam uintptr Time uint32 PtX int32 PtY int32 } hInstance, _, _ := getModuleHandle.Call(0) className := "SimpleWinClass" // Register the window class. wc := struct { Style uint32 LpfnWndProc uintptr CbClsExtra int32 CbWndExtra int32 HInstance uintptr HIcon uintptr HCursor uintptr HbrBackground uintptr LpszMenuName *uint16 LpszClassName *uint16 }{ Style: 0, LpfnWndProc: syscall.NewCallback(WndProc), CbClsExtra: 0, CbWndExtra: 0, HInstance: hInstance, HIcon: 0, HCursor: 0, HbrBackground: 0, LpszMenuName: nil, LpszClassName: (*uint16)(unsafe.Pointer(syscall.StringToUTF16Ptr(className))), } errCode, _, _ := user32.NewProc("RegisterClassW").Call(uintptr(unsafe.Pointer(&wc))) if errCode == 0 { fmt.Println("Failed to register window class.") return } // Create the window. hwnd, _, _ = createWindowEx.Call( 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(className))), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Learn Go GUI"))), 0x80000000|0x40000000|0xC00000, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 0, 0, hInstance, 0, ) if hwnd == 0 { fmt.Println("Failed to create window.") return } _, _, _ = showWindow.Call(hwnd, SW_SHOW) _, _, _ = updateWindow.Call(hwnd) for { ret, _, _ := GetMessage.Call(uintptr(unsafe.Pointer(&msg)), 0, 0, 0) if ret == 0 { break } translateMessage.Call(uintptr(unsafe.Pointer(&msg))) dispatchMessage.Call(uintptr(unsafe.Pointer(&msg))) } } func WndProc(hwnd uintptr, msg uint32, wParam uintptr, lParam uintptr) uintptr { switch msg { case 0x0010: // WM_CLOSE postQuitMessage.Call(0) return 0 default: defWindowProc := user32.NewProc("DefWindowProcW") ret, _, _ := defWindowProc.Call(hwnd, uintptr(msg), wParam, lParam) return ret } } ``` #### 解析 上述代码实现了以下功能: - 注册了一个自定义的窗口类[^1]。 - 创建了一个基本的窗口实例并显示出来。 - 实现了消息循环机制,用于处理窗口的消息队列。 需要注意的是,在实际开发中可能还需要引入更复杂的逻辑来支持更多的交互操作。此外,还可以借助第三方库如 `wui` 提高效率[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值