Я только учусь создавать графический интерфейс с помощью winapi, но я столкнулся с проблемой. Я могу создать такое окно
#include "stdafx.h"#include <windows.h>
int main()
{
HWND hwnd = CreateWindow(L"STATIC",NULL,WS_VISIBLE|WS_SYSMENU|WS_CAPTION,0,0,600,600,NULL,NULL,NULL,NULL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_gettch();
}
Но окна не закроются при нажатии кнопки закрытия, и окно нельзя перемещать или перемещать. Мне было интересно, как я мог бы включить эти функции окна.
Статических окон нет для обычных окон, вы должны попытаться найти и зарегистрировать свой собственный класс с помощью RegisterWindowEx, а затем использовать то же имя класса для создания окна. Вы должны иметь собственную оконную процедуру для обработки сообщений.
Все классы окон, зарегистрированные системой, запускают свои собственные процедуры окна по умолчанию, и, насколько я знаю, ни один из них не обрабатывает WM_CLOSE (то есть кнопку закрытия), поэтому вы не можете закрыть его.
Для вас в главных окнах всегда используйте что-то вроде WS_OVERLAPPEDWINDOW, поэтому будет ясно, все ли в порядке или нет, и из этого уберите ненужные вам флаги.
Как вы это настроили:
WNDCLASSEX wndcls;
HWND hMainWnd;
// Register your own window class
ZeroMemory(&wndcls,sizeof(WNDCLASSEX));
wndcls.cbSize=sizeof(WNDCLASSEX);
wndcls.style=CS_VREDRAW+CS_HREDRAW;
wndcls.lpfnWndProc=&appWndFunc;
wndcls.hInstance=hInstance;
wndcls.hIcon=hMainIcon; // or just LoadIcon(hInstance,MAKEINTRESOURCE(IDI_MAIN_ICON))
wndcls.hIconSm=hMainIcon;
wndcls.hCursor=LoadCursor((HINSTANCE)NULL,IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE;
wndcls.lpszClassName="myWndClass";
if (RegisterClassEx(&wndcls)==0)
{
// failed to register class name
return false;
}
// Create window with your own class
hMainWnd=CreateWindowEx(0,\
"myWndClass","widnow title",\
WS_OVERLAPPEDWINDOW|WS_VISIBLE,\
0,\
0,\
250,\
250,\
hMainWnd,NULL,hInstance,NULL);
if (hMainWnd==(HWND)NULL)
{
// failed to create main window
return false;
}
Тогда ваш основной цикл:
bool bAppMainLoop=false
while(!bAppMainLoop)
{
WaitMessage();
while(PeekMessage(&emsg,NULL,0,0,PM_NOREMOVE))
{
if(GetMessage(&emsg,NULL,0,0)==0)
{
bAppMainLoop=true;
break;
}
TranslateMessage(&emsg);
DispatchMessage(&emsg);
}
}
Это немного больше, чем обычная настройка, поэтому позвольте мне объяснить, чтобы не сжигать процессор, вы ждете сообщение с WaitMessage, оно будет блокироваться, пока что-то не произойдет, например, переместить окно, щелкнуть, нарисовать и т. Д. PeekMessage вернет true если существует сообщение, вызывающее его в цикле while, то оно гарантирует, что оно опустошит квену сообщения, GetMessage получит сообщение, если оно вернет 0, это означает, что ваше приложение вызвало PostQuitMessage (0), поэтому в сообщении найдено WM_QUIT цикл означает, что пришло время вырваться из цикла сообщений. Остальные Translate и Dispatch делают то, что написано.
Наконец, вам нужна собственная оконная процедура:
LRESULT CALLBACK appWndFunc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if (uMsg==WM_CLOSE)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
DefWindowProc необходим для обработки всех часто встречающихся сообщений из системы, поэтому вам не нужно обрабатывать их здесь. Вы просто отвечаете на сообщение WM_CLOSE, которое отправляется, когда вы хотите закрыть окно и отправить сообщение о выходе в цикл сообщений, который вы перехватите и выйдете.
Дополнительная информация :
Не нужно освобождать ваши вещи, так как Windows делает это за вас, поэтому они не будут заблокированы при следующем запуске вашей программы, но это хорошая практика, по крайней мере, отменить регистрацию вашего класса окна после основного цикла.
Кстати, это неправильная основная функция: WinMain это правильный. Плюс, чтобы избежать еще большего количества ошибок, убедитесь, что вы компилируете приложение с графическим интерфейсом Windows.
Других решений пока нет …