使用Win32 API调整窗口大小
Resizing window with Win32 API
我正在用Win32 API编写一个程序,只是为了掌握它,并且遇到了这个恼人的问题。一段时间后,调整窗口的大小最小化,并把它再次出现后,它是可见的,但不可点击,点击它只是激活它下面的窗口上的东西。唯一的解决办法就是退出程序。
起初我认为这是因为我的自定义功能的窗口大小(我使用自定义gui,不希望默认的窗口sizebox边界),但后来我重新激活了默认的sizebox和问题仍然存在。很难判断,但这个问题似乎总是在大致相同的时间/刻度被调整大小后发生。
我之前也遇到过类似的问题,窗口会最小化,然后在再次打开时变得完全白色,这出于某种原因是由调整大小函数中的for循环引起的。
我已经排除了代码中尽可能多的潜在问题,但仍然没有找到解决方案。下面是处理如何绘制窗口的所有代码的源文件(使用默认的sizebox)。
我很感激你的帮助。
p。我为任何糟糕的语言(非母语者),错误使用的术语或糟糕的语法道歉(第一次冒险进入API)。
//WinMain.cpp
#include <Windows.h>
#include "Utility.h"
#include "Mouse.h"
#include "AppInfo.h"
#include "Buttons.h"
//Function prototypes
ATOM MainRegister();
bool MainInit(HWND &hWnd, int nCmdShow);
void MatchRectToWnd(RECT &rect);
//Variables define in AppInfo.h
HRGN rgnMain, rgnCaptionbar;
bool _APPRUNNING = true;
const char _APPTITLE[] = "Dark";
//Variables
bool WIREFRAME = false;
//Pointers to buttons (singelton design)
btnCloseClass * btnCloseClass::s_Instance = 0;
btnMaximizeClass * btnMaximizeClass::s_Instance = 0;
btnMinimizeClass * btnMinimizeClass::s_Instance = 0;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDBLCLK: //Left mouse button double-clicked
Mouse.CheckDblClick(hWnd, wParam);
Mouse.m_Pressed = false;
break;
case WM_LBUTTONDOWN: //Left mouse button clicked
//Update the mouse position variables
GetCursorPos(&Mouse.prevPt);
GetCursorPos(&Mouse.m_LastClick);
Mouse.m_Pressed = true;
Mouse.CheckClickDown(hWnd);
break;
case WM_LBUTTONUP: //Left mouse button released
{
GetCursorPos(&Mouse.prevPt);
Mouse.CheckClickUp(hWnd);
Mouse.m_Pressed = false;
}
break;
case WM_SIZE: //Check if the window has been resized
{
//Update the buttons
btnClose->Update(hWnd);
btnMaximize->Update(hWnd);
btnMinimize->Update(hWnd);
//Update the regions
RECT rect; GetWindowRect(hWnd, &rect);
rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top);
rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT);
}
break;
case WM_PAINT: //Draw the window
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush;
hdc = BeginPaint(hWnd, &ps);
//Color the mainregion
hBrush = CreateSolidBrush(COLOR_MAIN);
FillRgn(hdc, rgnMain, hBrush);
//Color the captionbarregion
hBrush = CreateSolidBrush(COLOR_CAPTIONBAR);
FillRgn(hdc, rgnCaptionbar, hBrush);
//Color the button backgrounds
hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND);
FillRgn(hdc, btnClose->GetRegion(), hBrush);
FillRgn(hdc, btnMinimize->GetRegion(), hBrush);
FillRgn(hdc, btnMaximize->GetRegion(), hBrush);
//Color the button icons
hBrush = CreateSolidBrush(COLOR_BUTTON_ICON);
FillRgn(hdc, btnClose->GetIcon(), hBrush);
FillRgn(hdc, btnMinimize->GetIcon(), hBrush);
FillRgn(hdc, btnMaximize->GetIcon(), hBrush);
//Paint the wireframe
if (WIREFRAME)
{
hBrush = CreateSolidBrush(COLOR_WIREFRAME);
FrameRgn(hdc, rgnMain, hBrush, 1, 1);
FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1);
}
//Free up memomry
DeleteObject(hBrush);
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_TAB: //If TAB is pressed
{
if (WIREFRAME) //Activate the wireframe
WIREFRAME = false;
else
WIREFRAME = true;
InvalidateRgn(hWnd, NULL, true);
}
break;
case VK_ESCAPE: //If the ESCAPE is pressed
PostMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
}
break;
case WM_DESTROY: //Free up memory and exit the program
_APPRUNNING = false;
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
_APPRUNNING = true;
//Register the main window
if (!MainRegister())
{
MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR);
return false;
}
//Initialize the main window
MainInit(hWnd, nCmdShow);
//App-loop
while (_APPRUNNING)
{
if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated
{
Mouse.m_Pressed = false;
}
Mouse.Update(hWnd);
//Message-loop
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
bool MainInit(HWND &hWnd, int nCmdShow)
{
//Create the window
hWnd = CreateWindowEx(
WS_EX_LAYERED,
_APPTITLE,
_APPTITLE,
WS_OVERLAPPEDWINDOW,
0, 0, //Starting positons (x,y)
START_WIDTH, START_HEIGHT, //Width and height
NULL, //Parent-handle
NULL, //Menu-handle
GetModuleHandle(NULL),
NULL);
//Make sure the window was created properly
if (hWnd == NULL)
{
MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR);
return false;
}
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
//Get and set the window's style
DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE);
wndStyle &= ~(WS_CAPTION);
SetWindowLong(hWnd, GWL_STYLE, wndStyle);
//Create regions
rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT);
rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return true;
}
ATOM MainRegister()
{
//Create the window's classEx (extended class)
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = _APPTITLE;
wc.lpszMenuName = NULL;
wc.style = CS_DBLCLKS;
//Register the classEx
return RegisterClassEx(&wc);
}
正如@CodyGray所建议的,这里是工作代码以及处理释放区域内存的类和函数,现在画笔也是
编辑:这个问题是由创建WM_PAINT时的内存泄漏引起的,而不是删除,画笔(HBRUSH)。
//WinMain.cpp
#include <Windows.h>
#include "Utility.h"
#include "Mouse.h"
#include "AppInfo.h"
#include "Buttons.h"
//Function prototypes
ATOM MainRegister();
bool MainInit(HWND &hWnd, int nCmdShow);
void MatchRectToWnd(RECT &rect);
//Variables define in AppInfo.h
HRGN rgnMain, rgnCaptionbar;
bool _APPRUNNING = true;
const char _APPTITLE[] = "Dark";
//Variables
bool WIREFRAME = false;
//Pointers to buttons (singelton design)
btnCloseClass * btnCloseClass::s_Instance = 0;
btnMaximizeClass * btnMaximizeClass::s_Instance = 0;
btnMinimizeClass * btnMinimizeClass::s_Instance = 0;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDBLCLK: //Left mouse button double-clicked
Mouse.CheckDblClick(hWnd, wParam);
Mouse.m_Pressed = false;
break;
case WM_LBUTTONDOWN: //Left mouse button clicked
//Update the mouse position variables
GetCursorPos(&Mouse.prevPt);
GetCursorPos(&Mouse.m_LastClick);
Mouse.m_Pressed = true;
Mouse.CheckClickDown(hWnd);
break;
case WM_LBUTTONUP: //Left mouse button released
{
GetCursorPos(&Mouse.prevPt);
Mouse.CheckClickUp(hWnd);
Mouse.m_Pressed = false;
}
break;
case WM_SIZE: //Check if the window has been resized
{
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
//Update the buttons
btnClose->Update(hWnd);
btnMaximize->Update(hWnd);
btnMinimize->Update(hWnd);
//Update the regions
RECT rect; GetWindowRect(hWnd, &rect);
rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top);
rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT);
}
break;
case WM_PAINT: //Draw the window
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush;
hdc = BeginPaint(hWnd, &ps);
//Color the mainregion
hBrush = CreateSolidBrush(COLOR_MAIN);
FillRgn(hdc, rgnMain, hBrush);
DeleteObject(hBrush);
//Color the captionbarregion
hBrush = CreateSolidBrush(COLOR_CAPTIONBAR);
FillRgn(hdc, rgnCaptionbar, hBrush);
DeleteObject(hBrush);
//Color the button backgrounds
FillRgn(hdc, btnClose->GetRegion(), btnClose->GetBrush());
FillRgn(hdc, btnMinimize->GetRegion(), btnMinimize->GetBrush());
FillRgn(hdc, btnMaximize->GetRegion(), btnMaximize->GetBrush());
//Color the button icons
FillRgn(hdc, btnClose->GetIcon(), btnClose->GetBrushIcon());
FillRgn(hdc, btnMinimize->GetIcon(), btnMinimize->GetBrushIcon());
FillRgn(hdc, btnMaximize->GetIcon(), btnMaximize->GetBrushIcon());
//Paint the wireframe
if (WIREFRAME)
{
hBrush = CreateSolidBrush(COLOR_WIREFRAME);
FrameRgn(hdc, rgnMain, hBrush, 1, 1);
FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1);
DeleteObject(hBrush);
}
//Free up memomry
DeleteObject(hBrush);
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_TAB: //If TAB is pressed
{
if (WIREFRAME) //Activate the wireframe
WIREFRAME = false;
else
WIREFRAME = true;
InvalidateRgn(hWnd, NULL, true);
}
break;
case VK_ESCAPE: //If the ESCAPE is pressed
PostMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
}
break;
case WM_DESTROY: //Free up memory and exit the program
_APPRUNNING = false;
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
_APPRUNNING = true;
//Register the main window
if (!MainRegister())
{
MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR);
return false;
}
//Initialize the main window
MainInit(hWnd, nCmdShow);
//App-loop
while (_APPRUNNING)
{
if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated
{
Mouse.m_Pressed = false;
}
Mouse.Update(hWnd);
//Message-loop
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
bool MainInit(HWND &hWnd, int nCmdShow)
{
//Create the window
hWnd = CreateWindowEx(
WS_EX_LAYERED,
_APPTITLE,
_APPTITLE,
WS_OVERLAPPEDWINDOW,
0, 0, //Starting positons (x,y)
START_WIDTH, START_HEIGHT, //Width and height
NULL, //Parent-handle
NULL, //Menu-handle
GetModuleHandle(NULL),
NULL);
//Make sure the window was created properly
if (hWnd == NULL)
{
MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR);
return false;
}
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
//Get and set the window's style
DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE);
wndStyle &= ~(WS_CAPTION | WS_SIZEBOX);
SetWindowLong(hWnd, GWL_STYLE, wndStyle);
//Create regions
rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT);
rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return true;
}
ATOM MainRegister()
{
//Create the window's classEx (extended class)
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = _APPTITLE;
wc.lpszMenuName = NULL;
wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
//Register the classEx
return RegisterClassEx(&wc);
}
//Button.h
//Header file for the class responsible for handling the memory of the
//regions and brushes
class Button
{
protected:
//Protected default constructor
Button();
//Protected default destructor
~Button();
//Protected variables
HRGN m_Rgn;
HRGN m_Icon;
HBRUSH m_hBrush;
HBRUSH m_hBrush_Icon;
bool m_Hovered;
public:
//Public functions
virtual void CreateIcon() = 0;
virtual void Update(HWND hWnd) = 0;
bool Clicked(POINT pt);
bool CheckIfHovered(HWND hWnd);
HRGN GetRegion() { return m_Rgn; }
HRGN GetIcon() { return m_Icon; }
HBRUSH GetBrush() { return m_hBrush; }
HBRUSH GetBrushIcon() { return m_hBrush_Icon; }
};
//Button.cpp
//Default constructor
Button::Button()
{
m_hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND);
m_hBrush_Icon = CreateSolidBrush(COLOR_BUTTON_ICON);
m_Hovered = false;
}
//Default destructor
Button::~Button()
{
//Free up memory
DeleteObject(m_Rgn);
DeleteObject(m_Icon);
DeleteObject(m_hBrush);
DeleteObject(m_hBrush_Icon);
}
再次感谢@CodyGray @theB和@AdrianMcCarthy !
相关文章:
- SDL2 调整窗口大小后如何缩放鼠标坐标?
- GTK3 检测用户大小调整窗口
- 尝试在 win 32 中禁用窗口大小调整时,窗口样式行为不一致
- QGraphics手动调整窗口大小后场景宽度/高度没有变化
- Qt - 防止在拖动标题栏时调整窗口大小
- 在 Direct2D 绘图中,调整窗口大小后尺寸会更改
- WinAPI.检查窗口大小调整是否已完成
- 如何设置启用setFixize后再次调整主窗口大小
- 使用第二个线程快速更新 GUI 窗口会通过调整窗口大小或移动窗口而崩溃
- QT调整窗口大小后,删除窗口后
- 在Windows中平滑调整窗口大小(使用Direct2D 1.1)
- 捕获窗口大小调整
- 在opengl c++中禁用窗口大小调整
- Qt QSplitter 窗口大小调整时的固定高度小部件
- 如何捕获窗口大小调整
- WinAPI C++:重新编程窗口大小调整
- 设置控制台信息窗口大小调整不起作用 c++
- 改进窗口大小调整行为,可能通过手动设置更大的帧缓冲大小
- 在SDL 2中获得连续的窗口大小调整事件
- 仅允许垂直窗口大小调整的最简单方法是什么?