命令されてからでは遅い
Win01〜Win04で作ってたのはイベントドリブンという方式で、(イベント駆動型とも言う)
システムから命令されてから実行していた。
遅いので、
イベントが発生していない時に処理をしてしまおう。
というのが、
PeekMessage関数である。
実行サンプル
プログラム
#include <windows.h>
#include <windowsx.h>
HWND g_hwnd;
const int WINX = 320;
const int WINY = 240;
const char TITLE[] = "Win05";
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void Mainloop(HDC hdc);
HDC Back_Init_Surface(HWND hwnd)
{
HDC hdc,BackDC;
HBITMAP hBackBMP;
hdc=GetDC(hwnd);
BackDC=CreateCompatibleDC(hdc);
hBackBMP=CreateCompatibleBitmap(hdc,WINX,WINY);
SelectObject(BackDC,hBackBMP);
PatBlt(BackDC,0,0,WINX,WINY,WHITENESS);
DeleteObject(hBackBMP);
ReleaseDC(hwnd,hdc);
return BackDC;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
WNDCLASSEX wc;
HWND hwnd;
ZeroMemory(&wc,sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.lpszMenuName = NULL;
wc.hInstance = hInstance;
wc.hIcon = (HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_SHARED);
wc.hIconSm = (HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTCOLOR | LR_SHARED);
wc.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszClassName= TITLE;
if(!RegisterClassEx(&wc))return FALSE;
// ウィンドウのスタイル
// WS_OVERLAPPEDWINDOW = 大抵のやつを有効にしろ
// & ~WS_THICKFRAME = WS_OVERLAPPEDWINDOWからサイズ変更を無効に
// & ~WS_MAXIMIZEBOX = WS_OVERLAPPEDWINDOWから最大化を無効に
const DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
// ウィンドウを作る!
hwnd = CreateWindowEx(0,TITLE,TITLE,dwStyle,
GetSystemMetrics(SM_CXSCREEN)/2 - WINX/2, // 真ん中に表示
GetSystemMetrics(SM_CYSCREEN)/2 - WINY/2, // 真ん中に表示
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
if(!hwnd)return FALSE;
g_hwnd = hwnd;
//----- ウィンドウサイズをWINX WINY の大きさに。------
RECT window_rect;
SetRect(&window_rect,0,0,WINX,WINY);
AdjustWindowRectEx(&window_rect,GetWindowLong(hwnd,GWL_STYLE),GetMenu(hwnd) != NULL,GetWindowLong(hwnd,GWL_EXSTYLE));
const int nWidth = window_rect.right - window_rect.left;
const int nHeight = window_rect.bottom - window_rect.top;
SetWindowPos(hwnd,NULL,0,0,nWidth,nHeight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
//----- WINX WINY の大きさに。E -----
// ちらつきが起こるのでダブルバッファ
HDC BackDC = Back_Init_Surface(hwnd);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
HDC hdc=GetDC(hwnd);
int frame = 0; // 開始時からの合計フレーム数
bool active; // ウィンドウはアクティブ?
for(;;){
active = (hwnd == GetActiveWindow()) ? (IsIconic(hwnd)? true : false) : true;
// PeekMessage
if(active || PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
if(!GetMessage(&msg,(HWND)NULL,0,0))break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
// ウィンドウを白で塗りつぶし
PatBlt(BackDC,0,0,WINX,WINY,WHITENESS);
if(!active){
Mainloop(BackDC);
}
// メインの画面に描画
BitBlt(hdc,0,0,WINX,WINY,BackDC,0,0,SRCCOPY);
}
Sleep(1);// これを入れないと単なる無限ループ
}
ReleaseDC(hwnd,hdc);
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch(msg){
// Escを押された時だけDestroy処理が発生
case WM_KEYDOWN:
if(wParam != VK_ESCAPE){return 0;}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;
}
return (DefWindowProc(hwnd,msg,wParam,lParam));
}
static int x=0,y=0;
static const int speed = 1;
// メインループ
void Mainloop(HDC hdc){
if(GetKeyState(VK_UP ) & 0x80)y -= speed;
if(GetKeyState(VK_DOWN ) & 0x80)y += speed;
if(GetKeyState(VK_RIGHT) & 0x80)x += speed;
if(GetKeyState(VK_LEFT ) & 0x80)x -= speed;
TextOut(hdc,x,y,"Win05",5);
}