📄 window.cpp
字号:
#include "GKL.h"
using namespace GKL;
const int ID_REFRESH_EVENT = 255, T_REFRESH = 20;
bool Window::sMainWindowExists = false;
Window::Window(bool isMainWindow/* = true*/):
mhWnd(NULL),
mhMemDC(NULL),
mhMemBMP(NULL), mhMemBMPOld(NULL),
mIsMainWindow(isMainWindow),
mWidth(0), mHeight(0),
mDT(false, true), mET(false, true)
{
alert(mIsMainWindow && sMainWindowExists); // It's not allowed that there are more than one main window.
if(mIsMainWindow)
sMainWindowExists = true;
}
Window::~Window(void)
{
if(mhWnd != NULL)
destroy();
if(mIsMainWindow)
sMainWindowExists = false;
}
int Window::create(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPCWSTR caption)
{
WNDCLASSW wc;
if(!hPrevInstance)
{
wc.lpszClassName = L"GKL::Window";
wc.lpfnWndProc = Window::WndProcW;
wc.style = CS_OWNDC|CS_VREDRAW|CS_HREDRAW;
wc.hInstance = hInstance;
wc.hIcon = (HICON)LoadImage(NULL, L"crib.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG_PTR); // Use to hold the pointer to the Window Object
if(RegisterClassW(&wc) == 0)
return -1;
}
mhWnd = CreateWindowW(L"GKL::Window", caption, WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(mhWnd == NULL)
return -1;
SetLastError(0);
SetWindowLongPtr(mhWnd, GWLP_USERDATA, (LONG_PTR)this); // Hold the pointer to the Window Object
if(GetLastError() != 0)
return -1;
return 0;
}
int Window::show(int width, int height)
{
RECT workArea, wrect, crect;
mWidth = width;
mHeight = height;
ShowWindow(mhWnd, SW_SHOW);
UpdateWindow(mhWnd);
// Resize the window making the size of client area be suitable
// and move it to the center of the screen
SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
GetWindowRect(mhWnd, &wrect);
GetClientRect(mhWnd, &crect);
width = wrect.right - wrect.left;
height = wrect.bottom - wrect.top;
width += mWidth - (crect.right - crect.left) - 1;
height += mHeight - (crect.bottom - crect.top) - 1;
MoveWindow(mhWnd, workArea.left + (workArea.right - workArea.left - width)/2,
workArea.top + (workArea.bottom - workArea.top - height)/2, width, height, true);
// Prepare the memory DC
HDC hDC = GetDC(mhWnd);
mhMemDC = CreateCompatibleDC(hDC);
mhMemBMP = CreateCompatibleBitmap(hDC, mWidth, mHeight);
if((mhMemDC == NULL) || (mhMemBMP == NULL))
return -1;
mhMemBMPOld = (HBITMAP)SelectObject(mhMemDC, mhMemBMP);
return 0;
}
int Window::run(void)
{
if(SetTimer(mhWnd, ID_REFRESH_EVENT, T_REFRESH, Window::TimerProc) == 0)
return -1;
MSG msg;
BOOL bRet;
if(mIsMainWindow)
{
while((bRet=GetMessageW(&msg, NULL, 0, 0)) != 0)
{
if(bRet == -1)
{
// handle the error and possibly exit
return -1;
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
return 0;
}
void Window::destroy(void)
{
if(IsWindow(mhWnd))
{
KillTimer(mhWnd, ID_REFRESH_EVENT);
if(mhMemDC != NULL)
{
alert(mhMemBMP != SelectObject(mhMemDC, mhMemBMPOld));
mhMemBMPOld = NULL;
DeleteObject(mhMemBMP);
mhMemBMP = NULL;
DeleteDC(mhMemDC);
mhMemDC = NULL;
}
DestroyWindow(mhWnd);
mhWnd = NULL;
}
}
void Window::addDrawTrigger(Trigger *pTrigger)
{
mDT.addTrigger(pTrigger);
}
void Window::addEventTrigger(EventTrigger *pEventTrigger)
{
mET.addTrigger(pEventTrigger);
}
void Window::refresh(void)
{
RefreshParam rp;
rp.flag = REFRESH_ALL | METHOD_REFRESH;
mDT.trigger(&rp);
InvalidateRect(mhWnd, NULL, false);
}
HWND Window::gethWnd(void)
{
return mhWnd;
}
HDC Window::gethMemDC(void)
{
return mhMemDC;
}
void Window::getSize(int &width, int &height)
{
width = mWidth;
height = mHeight;
}
void Window::onRefresh(void)
{
RefreshParam rp;
rp.flag = METHOD_DETECT | REFRESH_NONE;
rp.pChanger = NULL;
mDT.trigger(&rp); // Prepare, make all Panels get ready, and determine whether redrawing is needed.
if((rp.flag & REFRESH_MASK) != REFRESH_NONE)
{
rp.flag = (rp.flag & REFRESH_MASK) | METHOD_REFRESH;
mDT.trigger(&rp); // Let the dirty Panels call BitBlt.
InvalidateRect(mhWnd, NULL, false);
}
}
void Window::onPaint(void)
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(mhWnd, &ps);
BitBlt(hDC, 0, 0, mWidth, mHeight, mhMemDC, 0, 0, SRCCOPY);
EndPaint(mhWnd, &ps);
}
LRESULT WINAPI Window::onKBEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProcW(mhWnd, uMsg, wParam, lParam);
mET.kbEvent(uMsg, wParam, lParam, lResult);
return lResult;
}
LRESULT WINAPI Window::onMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProcW(mhWnd, uMsg, wParam, lParam);
mET.mouseEvent(uMsg, wParam, lParam, lResult);
return lResult;
}
LRESULT WINAPI Window::WndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Window *pWnd = NULL;
switch(uMsg)
{
case WM_CHAR:
case WM_CHARTOITEM:
case WM_DEADCHAR:
case WM_GETHOTKEY:
case WM_HOTKEY:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SETHOTKEY:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
//case WM_UNICHAR:
case WM_VKEYTOITEM:
// The message list above is from Spy++
pWnd = (Window*)GetWindowLongPtr(hWnd, GWL_USERDATA);
return pWnd->onKBEvent(uMsg, wParam, lParam);
break;
case WM_DROPFILES:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEACTIVATE:
case WM_MOUSEHOVER:
case WM_MOUSELEAVE:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
case WM_PARENTNOTIFY:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_SETCURSOR:
//case WM_XBUTTONDBLCLK:
//case WM_XBUTTONDOWN:
//case WM_XBUTTONUP:
// The message list above is from Spy++
pWnd = (Window*)GetWindowLongPtr(hWnd, GWL_USERDATA);
return pWnd->onMouseEvent(uMsg, wParam, lParam);
break;
case WM_ERASEBKGND:
break;
case WM_PAINT:
pWnd = (Window*)GetWindowLongPtr(hWnd, GWL_USERDATA);
pWnd->onPaint();
break;
case WM_CLOSE:
pWnd = (Window*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(pWnd->mIsMainWindow)
//
// There exists a memory leak bug, if the main window was closed before
// the others, the program will quit before other Window Objects been
// released.
//
PostQuitMessage(0);
else
delete pWnd;
break;
default:
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
return 0;
}
VOID CALLBACK Window::TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
Window *pWnd = (Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
pWnd->onRefresh();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -