Win32 试验网上流传的 "窗口居中" 方案,到底哪种现在还有效
方案一:DS_CENTER(行不通)
原理:通过在注册类的时候,将起风格属性设置为居中,来使窗体居中
实验结果:失败
修改WNDCLASSEXW
的style
查了很多种方案后,有人说最简单的方法,是将WNDCLASSEXW
的风格添加上DS_CENTER
,就能实现居中,修改后的代码如下。经过测试发现,依旧无法居中
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.style = CS_HREDRAW | CS_VREDRAW | DS_CENTER;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST4));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TEST4);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
修改CreateWindow
的x
和y
CreateWindow
该函数创建一个重叠式窗口、弹出式窗口或子窗口。它指定窗口类,窗口标题,窗口风格,以及窗口的初始位置及大小(可选的)。函数也指该窗口的父窗口或所属窗口(如果存在的话),及窗口的菜单。
若要使用除 CreateWindow 函数支持的风格外的扩展风格,则使用 CreateWindowEx 函数代替 CreateWindow 函数。
CreateWindow的函数原型为
HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HANDLE hlnstance,
LPVOID lpParam
);
即使在创建窗口的函数 InitInstance
中,把 CreateWindowW
函数的 x
和y
都改成CW_USEDEFAULT
,依旧无法实现居中
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
方案二:GetSystemMetrics(可行)
原理:先获取屏幕大小,然后根据窗口大小进行计算,求出居中的x和y值
实验结果:窗口成功居中
屏幕整体尺寸,有以下三种方法
HDC hdc;
int cx, cy;
hdc = GetDC(NULL);
cx = GetDeviceCaps(hdc, DESKTOPHORZRES);
cy = GetDeviceCaps(hdc, DESKTOPVERTRES);
ReleaseDC(NULL, hdc);
//或
hdc = GetDC(NULL);
cx = GetDeviceCaps(hdc, HORZRES);
cy = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(NULL, hdc);
//或
cx = GetSystemMetrics(SM_CXSCREEN);
cy = GetSystemMetrics(SM_CYSCREEN);
获取不包含任务栏的屏幕尺寸
int cx, cy;
cx = GetSystemMetrics(SM_CXFULLSCREEN);
cy = GetSystemMetrics(SM_CYFULLSCREEN);
修改InitInstance
函数,居中窗口的坐标值如下
- x坐标为
x = (屏幕宽度 - 窗口宽度) / 2
- y坐标为
y = (屏幕高度 - 窗口高度) / 2
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目标: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
int width = 500;
int height = 500;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
(cx - width) / 2, (cy - height) / 2, width, height, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
实验结果:窗口成功居中
方案二:SetWindowPos(可行)
原理:在窗体创建完成后,根据屏幕大小和窗口位置进行调整,让窗口居中
实验结果:窗口成功居中
在注册窗口类的时候,会将事件绑定到WNDCLASSEXW
结构体的lpfnWndProc
属性上。这是一个函数指针,以后凡是有消息,都会发送给该函数
//
// 函数: MyRegisterClass()
//
// 目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST4));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TEST4);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
然后修改接收消息的WndProc
函数,在收到窗口创建完毕的消息后,根据屏幕大小,计算居中所需的窗口位置即可。通过SetWindowPos
函数,设置窗口位置
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目标: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
int scrWidth, scrHeight;
RECT rect;
//获得屏幕尺寸
scrWidth = GetSystemMetrics(SM_CXSCREEN);
scrHeight = GetSystemMetrics(SM_CYSCREEN);
//取得窗口尺寸
GetWindowRect(hWnd, &rect);
//重新设置rect里的值
rect.left = (scrWidth - rect.right) / 2;
rect.top = (scrHeight - rect.bottom) / 2;
//移动窗口到指定的位置
SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
- 点赞
- 收藏
- 关注作者
评论(0)