019 簡單的圖形1.1 -非常小WinAPI的包裝

Post date: 2015/2/5 上午 09:07:29

#ifndef __SG__ #define __SG__ #undef UNICODE #undef _UNICODE #include <windows.h> #include <string.h> #include <stdio.h> #include <iostream> #ifndef __cplusplus #define bool int #define true 1 #define false 0 #endif const int ID_MYBUTTON = 60001; HWND SGHWnd = 0; HDC SGWndDC = 0; #define SGDC SGWndDC bool _sgWndFreeze = false; int _sgMouseX = 0; int _sgMouseY = 0; int _sgMouseButtons = 0; int _sgWndUpdateInterval = 10; HANDLE _mainThread = 0; POINT _sgWndSize = {0}; /* Simple Graphics Functions -----------------------------------------*/ void sgCreateWindow (int width, int height); void sgCreateFullscreenWindow() {sgCreateWindow(0, 0);} int sgGetMouseX() {return _sgMouseX;} int sgGetMouseY() {return _sgMouseY;} int sgGetMouseButtons() {return _sgMouseButtons;} void sgSelectTool(HDC dc, HGDIOBJ tool); void sgWndFreeze(bool state); void sgSelectFont(const char *face, int pointSize, unsigned int flags); int sgGetTextExtentX(const char *text); int sgGetTextExtentY(const char *text); void sgTextOut(int x, int y, const char *text); /*---------------------------------------*/ enum { SG_FONT_NORMAL = 0x0, SG_FONT_BOLD = 0x1, SG_FONT_ITALIC = 0x2, SG_FONT_STRIKE = 0x4, SG_FONT_UNDERLINE = 0x8 }; void sgSelectTool(HDC dc, HGDIOBJ tool) { if (!GetObjectType(tool)) printf("\nSG_ERROR: The object is not exist!\n"); DeleteObject(SelectObject(dc, tool)); } void sgWndFreeze(bool state) { _sgWndFreeze = state; } void sgSelectFont(const char *face, int pointSize, unsigned int flags) { LOGFONT font ={0}; strcpy (font.lfFaceName, face); font.lfWeight = (flags & SG_FONT_BOLD) ? FW_SEMIBOLD : FW_NORMAL; font.lfItalic = flags & SG_FONT_ITALIC; font.lfUnderline = flags & SG_FONT_UNDERLINE; font.lfStrikeOut = flags & SG_FONT_STRIKE; font.lfHeight = -MulDiv(pointSize, GetDeviceCaps(SGWndDC, LOGPIXELSY), 72); font.lfCharSet = DEFAULT_CHARSET; sgSelectTool(SGWndDC, CreateFontIndirect(&font)); } int sgGetTextExtentX(const char *text) { SIZE textSize = {0}; GetTextExtentPoint32A(SGWndDC, text, strlen(text), &textSize); return textSize.cx; } int sgGetTextExtentY(const char *text) { SIZE textSize = {0}; GetTextExtentPoint32A(SGWndDC, text, strlen(text), &textSize); return textSize.cy; } void sgTextOut(int x, int y, const char *text) { TextOutA(SGWndDC, x, y , text, strlen(text)); GetPixel(SGWndDC, 0, 0); //dummy call } void _sgOnPaint (HWND wnd) { if (!_sgWndFreeze) { HDC dc = 0; PAINTSTRUCT ps = {0}; RECT r = {0}; SuspendThread(_mainThread); dc = BeginPaint (wnd, &ps); if (!dc) return; GetClientRect(wnd, &r); {POINT size = {r.right - r.left, r.bottom - r.top}; BitBlt (dc, 0, 0, size.x, size.y, SGWndDC, 0, 0, SRCCOPY);} ResumeThread(_mainThread); EndPaint (wnd, &ps); } } void _sgOnMouse (HWND hwnd, WPARAM buttons, LPARAM coords) { _sgMouseX = LOWORD(coords); _sgMouseY = HIWORD(coords); _sgMouseButtons = (int) buttons; } LRESULT CALLBACK _sgWindowProc (HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_DESTROY: CloseHandle(_mainThread); DeleteDC(SGWndDC); PostQuitMessage (0); exit(0); break; case WM_PAINT: _sgOnPaint(hwnd); break; case WM_TIMER: InvalidateRect(hwnd, NULL, false); UpdateWindow(hwnd); break; case WM_LBUTTONUP: case WM_LBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDOWN: case WM_MOUSEMOVE: _sgOnMouse(hwnd, wp, lp); break; } return DefWindowProc (hwnd, msg, wp, lp); } DWORD WINAPI _sgWndCycle (LPVOID fullscreen) { MSG msg = {0}; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, _sgWindowProc, 0, 0, NULL, NULL, LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, TEXT("SGWindow"), NULL}; int fullwidth = 2 * GetSystemMetrics (SM_CXFIXEDFRAME) + _sgWndSize.x; int fullheight = 2 * GetSystemMetrics (SM_CYFIXEDFRAME) + _sgWndSize.y + GetSystemMetrics (SM_CYCAPTION); DWORD style = WS_BORDER | WS_CAPTION | WS_SYSMENU; RegisterClassEx (&wc); if (*(bool *)fullscreen) { style = WS_POPUP; fullwidth = _sgWndSize.x; fullheight = _sgWndSize.y; } SGHWnd = CreateWindowExA (0, "SGWindow", "SGWindow", style, GetSystemMetrics(SM_CXSCREEN) / 2 - fullwidth / 2, GetSystemMetrics(SM_CYSCREEN) / 2 - fullheight / 2, fullwidth, fullheight, NULL, NULL, NULL, NULL); {HDC dc = GetDC(SGHWnd); HBITMAP bmap = CreateCompatibleBitmap(dc, _sgWndSize.x, _sgWndSize.y); SGWndDC = CreateCompatibleDC(dc); ReleaseDC(SGHWnd, dc); SelectObject (SGWndDC, bmap);} PatBlt(SGWndDC, 0, 0, _sgWndSize.x, _sgWndSize.y, PATCOPY); SelectObject(SGWndDC, GetStockObject(HOLLOW_BRUSH)); SetBkMode(SGWndDC, TRANSPARENT); SetTimer (SGHWnd, 0, _sgWndUpdateInterval, NULL); ShowWindow(SGHWnd, SW_SHOW); SetForegroundWindow(SGHWnd); UpdateWindow (SGHWnd); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return (DWORD) msg.wParam; } void sgCreateWindow(int width, int height) { bool fullscreen = false; if(SGHWnd) return; if (width == 0) { RECT r = {0}; fullscreen = true; GetWindowRect(GetDesktopWindow(), &r); _sgWndSize.x = r.right; _sgWndSize.y = r.bottom; } else { _sgWndSize.x = width; _sgWndSize.y = height; } DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &_mainThread, THREAD_SUSPEND_RESUME, FALSE, DUPLICATE_SAME_ACCESS); {DWORD threadId; CreateThread (NULL, 0, _sgWndCycle, &fullscreen, 0, &threadId);} while(!SGWndDC || GetForegroundWindow() != SGHWnd){ Sleep(10); } } #endif LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /* ************************************ * 功能顯示一個視窗 **************************************/ int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcx; // 視窗類 HWND hwnd; // 視窗處理 MSG msg; // 訊息 // 填充視窗類的資料結構 wcx.cbSize = sizeof(wcx);// 結構體的大小 wcx.style = CS_HREDRAW | CS_VREDRAW; // 樣式:大小改變時重繪介面 wcx.lpfnWndProc = WndProc; // 視窗訊息處理函數 wcx.cbClsExtra = 0; // 不使用類記憶體 wcx.cbWndExtra = 0; // 不使用視窗記憶體 wcx.hInstance = hinstance;// 所屬的應用程式實例處理 wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 圖示:使用預設值 wcx.hCursor = LoadCursor(NULL, IDC_ARROW);// 遊標:使用預設值 wcx.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH); // 背景:白色 wcx.lpszMenuName = NULL; // 選單:不使用 wcx.lpszClassName = TEXT("MainWClass");// 視窗類名 wcx.hIconSm = (HICON)LoadImage(hinstance,// 小圖示 MAKEINTRESOURCE(5), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); // 註冊視窗類 if(!RegisterClassEx(&wcx)) { return 1; } // 建立視窗 hwnd = CreateWindow( TEXT("MainWClass"), // 視窗名 TEXT("Test"), // 視窗標題 WS_OVERLAPPEDWINDOW,// 視窗樣式 100, // 水準位元置X:使用預設值 100, // 垂直位元置Y:使用預設值 640, // 寬度:使用預設值 480, // 高度:使用預設值 (HWND) NULL, // 父視窗:無 (HMENU) NULL, // 選單:使用視窗類的選單 hinstance, // 應用程式實例處理 (LPVOID) NULL); // 視窗建立時資料:無 if (!hwnd) { return 1; } // 顯示視窗 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 訊息迴圈 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } /* ************************************ * WndProc * 功能視窗訊息處理函數, 對所有的訊息都使用NULL處理函數 **************************************/ LRESULT CALLBACK WndProc(HWND hwnd,UINT Message,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (Message) { case WM_CREATE: { CreateWindow(TEXT("BUTTON"), TEXT("按鈕1"), WS_CHILD | WS_VISIBLE , 80, 135, 80, 20, hwnd, HMENU(ID_MYBUTTON), ((LPCREATESTRUCT)lParam)->hInstance, NULL); } break; case WM_COMMAND: // 剖析功能表選取項目: switch (LOWORD(wParam)) { case ID_MYBUTTON: { sgCreateWindow(800,600); sgTextOut(0,0,"hello"); //MessageBox(NULL, TEXT("ggg") ,TEXT("Error") , MB_OK); } break; default: return DefWindowProc(hwnd, Message, wParam, lParam); } break; case WM_KEYUP: { switch(wParam) { case VK_ESCAPE: { SendMessage(hwnd, WM_DESTROY, NULL, NULL); } break; } } break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // TODO: 在此加入任何繪圖程式碼... EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; }