<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Windows API 中的 GDI > 原文: [http://zetcode.com/gui/winapi/gdi/](http://zetcode.com/gui/winapi/gdi/) 圖形設備接口(GDI)是用于處理圖形的接口。 它用于與圖形設備(例如監視器,打印機或文件)進行交互。 GDI 允許程序員在屏幕或打印機上顯示數據,而不必擔心特定設備的詳細信息。 GDI 使程序員與硬件隔離。 從程序員的角度來看,GDI 是一組用于處理圖形的 API 函數。 GDI 由 2D 向量圖形,字體和圖像組成。 要開始繪制圖形,我們必須獲得設備上下文(DC)對象。 每當需要重繪窗口時,都會生成`WM_PAINT`消息。 程序員在窗口的客戶區域畫圖。 操作系統會自動繪制包括標題欄在內的周圍框架。 ```c HDC BeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint); ``` `BeginPaint()`函數為指定的繪圖準備窗口,并用繪圖信息填充`PAINTSTRUCT`結構。 它返回設備上下文的句柄。 設備上下文是我們執行繪制操作所通過的對象。 ```c BOOL EndPaint(HWND hWnd, const PAINTSTRUCT *lpPaint); ``` 每個繪圖操作都以`EndPaint()`結束。 每次調用`BeginPaint()`函數都需要此函數,但是僅在繪制完成之后才需要。 ## 像素點 像素是可以在視頻顯示系統中單獨處理的圖像的最小元素。 `SetPixel()`是在窗口上繪制單個像素的功能。 ```c COLORREF SetPixel(HDC hdc, int x, int y, COLORREF crColor); ``` 函數的第一個參數是設備上下文的句柄。 接下來的兩個參數是該點的 x 和 y 坐標。 最后一個參數是用于繪制點的顏色。 如果函數成功,則返回值為函數將像素設置為的 RGB 值。 `pixels.c` ```c #include <windows.h> #include <time.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void DrawPixels(HWND hwnd); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Pixels"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Pixels", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 250, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } srand(time(NULL)); return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: DrawPixels(hwnd); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void DrawPixels(HWND hwnd) { PAINTSTRUCT ps; RECT r; GetClientRect(hwnd, &r); if (r.bottom == 0) { return; } HDC hdc = BeginPaint(hwnd, &ps); for (int i=0; i<1000; i++) { int x = rand() % r.right; int y = rand() % r.bottom; SetPixel(hdc, x, y, RGB(255, 0, 0)); } EndPaint(hwnd, &ps); } ``` 在我們的示例中,我們在窗口的客戶區域隨機顯示 1000 個紅色像素。 ```c wc.style = CS_HREDRAW | CS_VREDRAW; ``` 這兩個標志會導致在調整窗口大小時重新繪制窗口。 ```c srand(time(NULL)); ``` `srand()`函數為隨機數生成器提供種子。 ```c case WM_PAINT: DrawPixels(hwnd); break; ``` 繪制是對`WM_PAINT`消息的反應。 實際圖形委托給`DrawPixels()`函數。 ```c HDC hdc = BeginPaint(hwnd, &ps); ``` `BeginPaint()`函數準備指定的窗口進行繪圖。 它用有關繪圖的信息填充`PAINTSTRUCT`結構。 它為指定窗口返回顯示設備上下文的句柄。 ```c GetClientRect(hwnd, &r); ``` 我們檢索窗口客戶區的坐標。 我們隨機在窗口上繪制,我們需要知道當前可以在哪里繪制。 ```c for (int i=0; i<1000; i++) { int x = rand() % r.right; int y = rand() % r.bottom; SetPixel(hdc, x, y, RGB(255, 0, 0)); } ``` 在窗口上隨機繪制一千個點。 `SetPixel()`函數使用所選顏色在指定位置繪制像素。 ```c EndPaint(hwnd, &ps); ``` 在繪圖的結尾,我們調用`EndPaint()`函數。 該函數釋放`BeginPaint()`檢索到的顯示設備上下文。 ![Pixels](https://img.kancloud.cn/6e/e3/6ee3ec04031250c8940aee2bc36caba3_300x250.jpg) 圖:像素 ## 直線 線是基本的圖形基元。 它具有兩個函數:`MoveToEx()`和`LineTo()`。 ```c BOOL MoveToEx(HDC hdc, int x, int y, LPPOINT lpPoint); ``` `MoveToEx()`函數將當前位置更新到指定點,并有選擇地返回先前位置。 ```c BOOL LineTo(HDC hdc, int nXEnd, int nYEnd); ``` `LineTo()`函數從當前位置開始繪制一條線,但不包括指定點。 `lines.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Lines"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Lines", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 200, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); MoveToEx(hdc, 50, 50, NULL); LineTo(hdc, 250, 50); HPEN hWhitePen = GetStockObject(WHITE_PEN); HPEN hOldPen = SelectObject(hdc, hWhitePen); MoveToEx(hdc, 50, 100, NULL); LineTo(hdc, 250, 100); SelectObject(hdc, hOldPen); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 這個例子畫了兩條線。 一種是黑色,另一種是白色。 ```c MoveToEx(hdc, 50, 50, NULL); LineTo(hdc, 250, 50); ``` 在點(50,50)和(250,50)之間繪制了一條線。 使用默認的`BLACK_PEN`。 ```c HPEN hWhitePen = GetStockObject(WHITE_PEN); ``` `GetStockObject()`函數檢索用`WHITE_PEN`值指定的內置白筆的句柄。 通過調用`DeleteObject()`不必刪除庫存對象(但這不是有害的)。 ```c HPEN hOldPen = SelectObject(hdc, hWhitePen); ``` `SelectObject()`函數將一個對象選擇到指定的設備上下文(DC)中。 新對象將替換相同類型的先前對象。 ```c SelectObject(hdc, hOldPen); ``` 我們恢復到舊的`BLACK_PEN`筆。 ![Lines](https://img.kancloud.cn/3a/c1/3ac1608b5c384052859a41505eaeb0b2_300x200.jpg) 圖:直線 ## 長方形 要繪制矩形,我們使用`Rectangle()`函數。 ```c BOOL Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); ``` 函數的第一個參數是設備上下文的句柄。 接下來的兩個參數是矩形左上角的 x 和 y 坐標。 最后兩個參數是矩形右下角的 x,y 坐標。 如果函數失敗,則返回值為零。 如果成功,則返回值為非零。 `rectangle.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Rectangle"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Rectangle", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); Rectangle(hdc, 50, 50, 200, 100); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 使用當前的筆繪制矩形的輪廓。 使用當前畫筆繪制背景。 ```c Rectangle(hdc, 50, 50, 200, 100); ``` 使用`Rectangle()`函數繪制矩形。 我們使用兩個點繪制矩形:左上角點和右下角點。 ![Rectangle](https://img.kancloud.cn/dc/1c/dc1c181cc92e35056824b340af47fb34_250x200.jpg) 圖:矩形 ## 貝塞爾曲線 貝塞爾曲線是由數學公式定義的曲線。 繪制曲線的數學方法由 PierreBézier 在 1960 年代后期創建,用于雷諾的汽車制造。 ```c BOOL PolyBezier(HDC hdc, const POINT *lppt, DWORD cPoints); ``` 函數的第一個參數是設備上下文的句柄。 第二個參數是指向`POINT`結構數組的指針,該數組包含曲線的端點和控制點。 `beziercurve.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"BezierCurve"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Beziér curve", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 200, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; POINT points[4] = { 20, 40, 320, 200, 330, 110, 450, 40 }; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); PolyBezier(hdc, points, 4); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 在示例中,我們使用`PolyBezier()`函數繪制一條曲線。 ```c POINT points[4] = { 20, 40, 320, 200, 330, 110, 450, 40 }; ``` 這些點形成貝塞爾曲線。 第一點是起點。 接下來的兩個點是控制點。 最后一點是曲線的終點。 ```c PolyBezier(hdc, points, 4); ``` `PolyBezier()`函數繪制曲線。 ![Bézier curve](https://img.kancloud.cn/13/ed/13ed1fbc729c71aeb786f6802db43bcd_500x200.jpg) 圖:貝塞爾曲線 ## 鋼筆 筆是基本圖形對象。 它用于繪制矩形,橢圓形,多邊形或其他形狀的線,曲線和輪廓。 筆有兩種類型:化妝筆和幾何筆。化妝筆是固定寬度為 1 的簡單筆。它們具有三個屬性:寬度,樣式和顏色。 它們比幾何筆更有效。 可以使用`CreatePen()`,`CreatePenIndirect()`或`ExtCreatePen()`函數創建化妝筆。 幾何筆比化妝筆復雜。 它們具有七個屬性:寬度,樣式,顏色,圖案,剖面線,端蓋和連接樣式。 幾何筆是使用`ExtCreatePen()`函數創建的。 ```c HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor); ``` `CreatePen()`函數創建具有指定樣式,寬度和顏色的邏輯筆。 ```c HPEN ExtCreatePen(DWORD dwPenStyle, DWORD dwWidth, const LOGBRUSH *lplb, DWORD dwStyleCount, const DWORD *lpStyle); ``` `ExtCreatePen()`函數創建邏輯的化妝筆或幾何筆。 第一個參數是類型,樣式,端蓋和聯接屬性的組合。 第二個參數是筆的寬度。 第三個參數是指向`LOGBRUSH`結構的指針。 該結構定義了物理筆刷的樣式,顏色和圖案。 第四個參數是`lpStyle`數組的長度,以`DWORD`單位。 如果`dwPenStyle`不是`PS_USERSTYLE`,則此值必須為零。 樣式計數限制為 16。最后一個參數是指向數組的指針。 第一個值以用戶定義的樣式指定第一個筆劃線的長度,第二個值指定第一個空格的長度,依此類推。 如果`dwPenStyle`不是`S_USERSTYLE`,則此指針必須為`NULL`。 創建筆后,我們使用`SelectObject()`函數將其選擇到應用的設備上下文中。 從現在開始,應用使用此筆在其客戶區中進行任何畫線操作。 ### 筆樣式 筆樣式是應用于線對象的特定圖案。 有預定義的筆樣式,例如`PS_SOLID`,`PS_DASH`,`PS_DOT`或`PS_DASHDOT`。 也可以創建自定義筆樣式。 `penstyles.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void DrawLines(HWND); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Pen styles"; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Pen styles", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 180, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: DrawLines(hwnd); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void DrawLines(HWND hwnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HPEN hPen1 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); HPEN hPen2 = CreatePen(PS_DASH, 1, RGB(0, 0, 0)); HPEN hPen3 = CreatePen(PS_DOT, 1, RGB(0, 0, 0)); HPEN hPen4 = CreatePen(PS_DASHDOT, 1, RGB(0, 0, 0)); HPEN hPen5 = CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 0)); HPEN holdPen = SelectObject(hdc, hPen1); MoveToEx(hdc, 50, 30, NULL); LineTo(hdc, 300, 30); SelectObject(hdc, hPen2); MoveToEx(hdc, 50, 50, NULL); LineTo(hdc, 300, 50); SelectObject(hdc, hPen2); MoveToEx(hdc, 50, 70, NULL); LineTo(hdc, 300, 70); SelectObject(hdc, hPen3); MoveToEx(hdc, 50, 90, NULL); LineTo(hdc, 300, 90); SelectObject(hdc, hPen4); MoveToEx(hdc, 50, 110, NULL); LineTo(hdc, 300, 110); SelectObject(hdc, holdPen); DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3); DeleteObject(hPen4); DeleteObject(hPen5); EndPaint(hwnd, &ps); } ``` 在我們的示例中,我們使用五種不同的筆樣式繪制五根不同的線。 ```c case WM_PAINT: DrawLines(hwnd); break; ``` 實際圖形委托給`DrawLines()`函數。 ```c HPEN hPen1 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); ``` `CreatePen()`函數創建具有指定樣式,寬度和顏色的邏輯筆。 `PS_SOLID`代表實心筆。 我們使用`RGB`宏為筆生成顏色。 ```c SelectObject(hdc, hPen1); ``` 要激活筆,我們調用`SelectObject()`函數。 ```c MoveToEx(hdc, 50, 30, NULL); LineTo(hdc, 300, 30); ``` 要繪制線條,我們使用`MoveToEx()`和`LineTo()`函數。 ```c DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3); DeleteObject(hPen4); DeleteObject(hPen5); ``` 最后,我們清理資源。 ![Pen styles](https://img.kancloud.cn/d8/dc/d8dcf46768fd50b849841e7420b843ec_350x180.jpg) 圖:筆的樣式 ### 直線連接 可以使用三種不同的連接樣式來連接線:`PS_JOIN_BEVEL`,`PS_JOIN_MITEl`和`PS_JOIN_ROUND`。 `linejoins.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void DoDrawing(HWND); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Pens"; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Line joins", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 450, 200, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: DoDrawing(hwnd); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void DoDrawing(HWND hwnd) { LOGBRUSH brush; COLORREF col = RGB(0, 0, 0); DWORD pen_style = PS_SOLID | PS_JOIN_MITER | PS_GEOMETRIC; brush.lbStyle = BS_SOLID; brush.lbColor = col; brush.lbHatch = 0; PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HPEN hPen1 = ExtCreatePen(pen_style, 8, &brush, 0, NULL); HPEN holdPen = SelectObject(hdc, hPen1); POINT points[5] = { { 30, 30 }, { 130, 30 }, { 130, 100 }, { 30, 100 }, { 30, 30}}; Polygon(hdc, points, 5); pen_style = PS_SOLID | PS_GEOMETRIC | PS_JOIN_BEVEL; HPEN hPen2 = ExtCreatePen(pen_style, 8, &brush, 0, NULL); SelectObject(hdc, hPen2); DeleteObject(hPen1); POINT points2[5] = { { 160, 30 }, { 260, 30 }, { 260, 100 }, { 160, 100 }, {160, 30 }}; MoveToEx(hdc, 130, 30, NULL); Polygon(hdc, points2, 5); pen_style = PS_SOLID | PS_GEOMETRIC | PS_JOIN_ROUND; HPEN hPen3 = ExtCreatePen(pen_style, 8, &brush, 0, NULL); SelectObject(hdc, hPen3); DeleteObject(hPen2); POINT points3[5] = { { 290, 30 }, { 390, 30 }, { 390, 100 }, { 290, 100 }, {290, 30 }}; MoveToEx(hdc, 260, 30, NULL); Polygon(hdc, points3, 5); SelectObject(hdc, holdPen); DeleteObject(hPen3); EndPaint(hwnd, &ps); } ``` 在示例中,我們顯示了矩形上的三種類型的線連接。 ```c pen_style = PS_SOLID | PS_GEOMETRIC | PS_JOIN_BEVEL; HPEN hPen2 = ExtCreatePen(pen_style, 8, &brush, 0, NULL); ``` `ExtCreatePen()`函數創建一個帶有`PS_JOIN_BEVEL`連接的實心幾何筆。 ```c POINT points2[5] = { { 160, 30 }, { 260, 30 }, { 260, 100 }, { 160, 100 }, {160, 30 }}; MoveToEx(hdc, 130, 30, NULL); Polygon(hdc, points2, 5); ``` 從提供的點開始,我們使用`Polygon()`函數創建一個矩形。 ![Line joins](https://img.kancloud.cn/f3/3a/f33ae33bc658cfcba008215ef61b89ca_450x200.jpg) 圖:直線連接 ## 筆刷 畫筆是基本圖形對象。 它用于繪制圖形形狀的背景,例如矩形,橢圓形或多邊形。 筆刷可以是純色,陰影線或自定義位圖圖案。 ### 實心筆刷 實心畫筆是一種顏色。 它是用`CreateSolidBrush()`函數創建的。 ```c HBRUSH CreateSolidBrush(COLORREF crColor); ``` `CreateSolidBrush()`函數創建具有指定純色的畫筆。 `solidbrush.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void DrawRectangles(HWND); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Brush"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Solid Brush", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 220, 240, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: DrawRectangles(hwnd); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void DrawRectangles(HWND hwnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0)); HPEN holdPen = SelectObject(hdc, hPen); HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0)); HBRUSH hBrush2 = CreateSolidBrush(RGB(240, 63, 19)); HBRUSH hBrush3 = CreateSolidBrush(RGB(240, 210, 18)); HBRUSH hBrush4 = CreateSolidBrush(RGB(9, 189, 21)); HBRUSH holdBrush = SelectObject(hdc, hBrush1); Rectangle(hdc, 30, 30, 100, 100); SelectObject(hdc, hBrush2); Rectangle(hdc, 110, 30, 180, 100); SelectObject(hdc, hBrush3); Rectangle(hdc, 30, 110, 100, 180); SelectObject(hdc, hBrush4); Rectangle(hdc, 110, 110, 180, 180); SelectObject(hdc, holdPen); SelectObject(hdc, holdBrush); DeleteObject(hPen); DeleteObject(hBrush1); DeleteObject(hBrush2); DeleteObject(hBrush3); DeleteObject(hBrush4); EndPaint(hwnd, &ps); } ``` 在示例中,我們創建了 4 個矩形,其中填充了 4 種不同的純色。 ```c HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0)); ``` 在這里,我們創建一個純色筆刷。 ```c HBRUSH holdBrush = SelectObject(hdc, hBrush1); ``` 在設備上下文中選擇了一個新畫筆。 ![Solid brushes](https://img.kancloud.cn/8a/7b/8a7bb44358e90921a74de118a810b111_220x240.jpg) 圖:實心刷 ### 艙口筆刷 有六種預定義的艙口筆刷。 在我們的示例中,我們展示了所有這些。 ```c HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref); ``` `CreateHatchBrush()`函數創建具有指定填充圖案和顏色的畫筆。 `hatchbrushes.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void DrawRectangles(HWND hwnd); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_VREDRAW | CS_HREDRAW; wc.lpszClassName = L"Brush"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Hatch brushes", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 220, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: DrawRectangles(hwnd); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } void DrawRectangles(HWND hwnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0)); HPEN holdPen = SelectObject(hdc, hPen); HBRUSH hBrush1 = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0)); HBRUSH hBrush2 = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 0, 0)); HBRUSH hBrush3 = CreateHatchBrush(HS_CROSS, RGB(0, 0, 0)); HBRUSH hBrush4 = CreateHatchBrush(HS_HORIZONTAL, RGB(0, 0, 0)); HBRUSH hBrush5 = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 0)); HBRUSH hBrush6 = CreateHatchBrush(HS_VERTICAL, RGB(0, 0, 0)); HBRUSH holdBrush = SelectObject(hdc, hBrush1); DWORD col = GetSysColor(COLOR_BTNFACE); SetBkColor(hdc, col); Rectangle(hdc, 30, 30, 100, 80); SelectObject(hdc, hBrush2); Rectangle(hdc, 110, 30, 180, 80); SelectObject(hdc, hBrush3); Rectangle(hdc, 190, 30, 260, 80); SelectObject(hdc, hBrush4); Rectangle(hdc, 30, 110, 100, 160); SelectObject(hdc, hBrush5); Rectangle(hdc, 110, 110, 180, 160); SelectObject(hdc, hBrush6); Rectangle(hdc, 190, 110, 260, 160); SelectObject(hdc, holdPen); SelectObject(hdc, holdBrush); DeleteObject(hPen); DeleteObject(hBrush1); DeleteObject(hBrush2); DeleteObject(hBrush3); DeleteObject(hBrush4); DeleteObject(hBrush5); DeleteObject(hBrush6); EndPaint(hwnd, &ps); } ``` 此示例與上一個示例非常相似。 我們僅使用一個新的函數調用`CreateHatchBrush()`。 ```c HBRUSH hBrush1 = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0)); ``` 將創建對角線陰影筆刷。 ```c HBRUSH holdBrush = SelectObject(hdc, hBrush1); ``` 畫筆被選擇到設備上下文中。 返回舊畫筆的句柄。 ```c DeleteObject(hBrush1); ``` 筆刷對象被刪除。 ![Hatch brushes](https://img.kancloud.cn/6b/23/6b232c3311c285026042fc33c8c8259b_300x220.jpg) 圖:艙口刷 ### 定制筆刷 可以使用`CreatePatternBrush()`函數創建自定義畫筆。 ```c HBRUSH CreatePatternBrush(HBITMAP hbmp); ``` 該函數獲取要用于創建畫筆的位圖的句柄。 `custombrush.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Custom brush"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Custom brush", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 200, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static HBITMAP hBtm; UINT bits[8] = { 0x111111ff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; switch(msg) { case WM_CREATE: hBtm = CreateBitmap(8, 8, 1, 1, (LPBYTE) bits); break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); HBRUSH hCustomBrush = CreatePatternBrush(hBtm); HBRUSH hOldBrush = SelectObject(hdc, hCustomBrush); SelectObject(hdc, GetStockObject(NULL_PEN)); Rectangle(hdc, 20, 20, 250, 160); SelectObject(hdc, hOldBrush); DeleteObject(hCustomBrush); SelectObject(hdc, GetStockObject(BLACK_PEN)); EndPaint(hwnd, &ps); break; case WM_DESTROY: DeleteObject(hBtm); PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 該示例繪制了一個矩形。 其內部充滿了自定義的畫筆圖案。 ```c hBtm = CreateBitmap(8, 8, 1, 1, (LPBYTE) bits); ``` 我們使用`CreateBitmap()`函數創建位圖圖案。 ```c HBRUSH hCustomBrush = CreatePatternBrush(hBtm); ``` `CreatePatternBrush()`函數從提供的位圖創建畫筆對象。 ```c HBRUSH hOldBrush = SelectObject(hdc, hCustomBrush); ``` 我們使用`SelectObject()`函數選擇自定義畫筆。 ```c SelectObject(hdc, GetStockObject(NULL_PEN)); ``` 我們不會繪制矩形的輪廓。 當我們選擇`NULL_PEN`時,沒有畫出輪廓。 ```c Rectangle(hdc, 20, 20, 250, 160); ``` 矩形用`Rectangle()`函數繪制; 其內部使用選定的自定義畫筆繪制。 ![Custom brush](https://img.kancloud.cn/03/e6/03e60b07dfef67f382f88c242924fa04_300x200.jpg) 圖:自定義刷 ## 形狀 形狀是更復雜的幾何對象。 在下面的示例中,我們將繪制各種幾何形狀。 `shapes.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Shapes"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Shapes", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 390, 230, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; const POINT polygon[10] = { 30, 145, 85, 165, 105, 110, 65, 125, 30, 105 }; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); Ellipse(hdc, 30, 30, 120, 90); RoundRect(hdc, 150, 30, 240, 90, 15, 20); Chord(hdc, 270, 30, 360, 90, 270, 45, 360, 45); Polygon(hdc, polygon, 5); Rectangle(hdc, 150, 110, 230, 160); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 在我們的示例中,我們創建了一個橢圓,一個圓角矩形,一個弦,一個多邊形和一個矩形。 ```c Ellipse(hdc, 30, 30, 120, 90); ``` `Ellipse()`函數繪制一個橢圓。 `Ellipse()`的參數是邊界矩形的左上角和右下角的 x 和 y 坐標。 在此矩形內繪制橢圓。 ```c RoundRect(hdc, 150, 30, 240, 90, 15, 20); ``` `RoundRect()`函數繪制帶有圓角的矩形。 `RoundRect()`的參數是邊界矩形的左上角和右下角的 x 和 y 坐標。 最后兩個參數是用于繪制圓角的橢圓的寬度和高度。 ```c Chord(hdc, 270, 30, 360, 90, 270, 45, 360, 45); ``` `Chord()`函數繪制和弦。 和弦是由橢圓和線段的交點界定的區域。 前四個參數是邊界矩形的左上角的 x 和 y 坐標以及右下角的 x 和 y 坐標。 接下來的四個參數是定義弦的起點的徑向的 x 和 y 坐標以及定義弦的終點的徑向的 x 和 y 坐標。 ```c Polygon(hdc, polygon, 5); ``` `Polygon()`函數繪制由兩個或多個通過直線連接的頂點組成的多邊形。 多邊形是指向`POINT`結構數組的指針,該數組指定多邊形的頂點。 最后一個參數是數組中的點數。 ```c Rectangle(hdc, 150, 110, 230, 160); ``` `Rectangle()`函數繪制一個矩形。 該函數的參數是矩形左上角和右下角的 x 和 y 坐標。 ![Shapes](https://img.kancloud.cn/73/0c/730c7080c5a2c53bd8f238181e1529f0_390x230.jpg) 圖:形狀 ## 星形 在下面的示例中,我們使用`Polyline()`函數繪制星形。 ```c BOOL Polyline(HDC hdc, const POINT *lppt, int cPoints); ``` `Polyline()`函數通過連接指定數組中的點來繪制一系列線段。 函數的第一個參數是設備上下文的句柄。 第二個參數是指向`POINT`結構數組的指針。 第三個參數是數組中的點數。 此數字必須大于或等于 2。 `star.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Star"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Star", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 300, 250, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; POINT points[11] = { { 10, 85 }, { 85, 75 }, { 110, 10 }, { 135, 75 }, { 210, 85 }, { 160, 125 }, { 170, 190 }, { 110, 150 }, { 50, 190 }, { 60, 125 }, { 10, 85 } }; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); Polyline(hdc, points, 11); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 該示例繪制一個星形對象。 ```c POINT points[11] = { { 10, 85 }, { 85, 75 }, { 110, 10 }, { 135, 75 }, { 210, 85 }, { 160, 125 }, { 170, 190 }, { 110, 150 }, { 50, 190 }, { 60, 125 }, { 10, 85 } }; ``` 這是恒星的`POINTS`的數組。 ```c Polyline(hdc, points, 11); ``` `Polyline()`函數繪制星形。 ![Star](https://img.kancloud.cn/c6/62/c662a6f8a203e1300ecdcd985dae12fb_300x250.jpg) 圖:星星 ## 文本 `TextOutW()`函數使用當前選擇的字體,背景色和文本色在指定位置寫入字符串。 ```c BOOL TextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cchString); ``` 函數的第一個參數是設備上下文的句柄。 接下來的兩個參數是系統用于對齊字符串的參考點的 x 和 y 坐標。 第三個參數是指向要繪制的字符串的指針。 最后一個參數是字符串的長度。 `sonnet55.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg ; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Sonnet 55"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Sonnet 55", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 390, 350, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; DWORD color; HFONT hFont, holdFont; static wchar_t *ver1 = L"Not marble, nor the gilded monuments"; static wchar_t *ver2 = L"Of princes, shall outlive this powerful rhyme;"; static wchar_t *ver3 = L"But you shall shine more bright in these contents"; static wchar_t *ver4 = L"Than unswept stone, besmear'd with sluttish time."; static wchar_t *ver5 = L"When wasteful war shall statues overturn,"; static wchar_t *ver6 = L"And broils root out the work of masonry,"; static wchar_t *ver7 = L"Nor Mars his sword, nor war's quick fire shall burn"; static wchar_t *ver8 = L"The living record of your memory."; static wchar_t *ver9 = L"'Gainst death, and all oblivious enmity"; static wchar_t *ver10 = L"Shall you pace forth; your praise shall still find room"; static wchar_t *ver11 = L"Even in the eyes of all posterity"; static wchar_t *ver12 = L"That wear this world out to the ending doom."; static wchar_t *ver13 = L"So, till the judgment that yourself arise,"; static wchar_t *ver14 = L"You live in this, and dwell in lovers' eyes."; switch(msg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); color = GetSysColor(COLOR_BTNFACE); SetBkColor(hdc, color); hFont = CreateFontW(15, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, L"Georgia"); holdFont = SelectObject(hdc, hFont); TextOutW(hdc, 50, 20, ver1, lstrlenW(ver1)); TextOutW(hdc, 50, 40, ver2, lstrlenW(ver2)); TextOutW(hdc, 50, 60, ver3, lstrlenW(ver3)); TextOutW(hdc, 50, 80, ver4, lstrlenW(ver4)); TextOutW(hdc, 50, 100, ver5, lstrlenW(ver5)); TextOutW(hdc, 50, 120, ver6, lstrlenW(ver6)); TextOutW(hdc, 50, 140, ver7, lstrlenW(ver7)); TextOutW(hdc, 50, 160, ver8, lstrlenW(ver8)); TextOutW(hdc, 50, 180, ver9, lstrlenW(ver9)); TextOutW(hdc, 50, 200, ver10, lstrlenW(ver10)); TextOutW(hdc, 50, 220, ver11, lstrlenW(ver11)); TextOutW(hdc, 50, 240, ver12, lstrlenW(ver12)); TextOutW(hdc, 50, 260, ver13, lstrlenW(ver13)); TextOutW(hdc, 50, 280, ver14, lstrlenW(ver14)); SelectObject(hdc, holdFont); DeleteObject(hFont); EndPaint(hwnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 我們使用`TextOutW()`函數在窗口上繪制幾節經文。 ```c color = GetSysColor(COLOR_BTNFACE); SetBkColor(hdc, color); ``` 默認情況下,如果我們在窗口的工作區上繪制一些文本,則背景設置為白色。 我們可以通過使用`SetBkColor()`函數設置背景顏色來更改此設置。 我們使用了典型的 Windows 灰色。 `GetSysColor()`函數用于獲取按鈕,標題或窗口控件背景中使用的系統顏色。 ```c hFont = CreateFontW(15, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, L"Georgia"); holdFont = SelectObject(hdc, hFont); ``` 在這里,我們使用`CreateFontW()`函數創建一個字體對象。 該函數有 14 個參數; 我們不必全部指定。 我們僅指定字體大小,字體粗細和 fontface 參數。 ```c TextOutW(hdc, 50, 20, verse1, lstrlenW(verse1)); ``` 使用`TextOutW()`函數將文本繪制到窗口上。 字符串的長度由`lstrlenW()`函數確定。 ![Text](https://img.kancloud.cn/e4/b9/e4b952952db0a4073ff6affa925f2b32_390x350.jpg) 圖:文本 ## 繪制位圖 位圖是一個圖形對象,用于創建,處理圖像并將其作為文件存儲在磁盤上。 BMP 是 Windows 的本機位圖格式,實際上用于存儲任何類型的位圖數據。 `drawbitmap.c` ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = L"Draw Bitmap"; wc.hInstance = hInstance; wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassW(&wc); CreateWindowW(wc.lpszClassName, L"Draw Bitmap", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 280, 220, NULL, NULL, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HBITMAP hBitmap; HDC hdc; PAINTSTRUCT ps; BITMAP bitmap; HDC hdcMem; HGDIOBJ oldBitmap; switch(msg) { case WM_CREATE: hBitmap = (HBITMAP) LoadImageW(NULL, L"C:\\prog\\slovakia.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (hBitmap == NULL) { MessageBoxW(hwnd, L"Failed to load image", L"Error", MB_OK); } break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); hdcMem = CreateCompatibleDC(hdc); oldBitmap = SelectObject(hdcMem, hBitmap); GetObject(hBitmap, sizeof(bitmap), &bitmap); BitBlt(hdc, 5, 5, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); SelectObject(hdcMem, oldBitmap); DeleteDC(hdcMem); EndPaint(hwnd, &ps); break; case WM_DESTROY: DeleteObject(hBitmap); PostQuitMessage(0); return 0; } return DefWindowProcW(hwnd, msg, wParam, lParam); } ``` 該示例在窗口上繪制了斯洛伐克國旗。 圖片為 BMP 文件格式。 ```c static HBITMAP hBitmap; ``` `HBITMAP`是位圖對象的句柄。 ```c BITMAP bitmap; ``` `BITMAP`結構定義位圖的類型,寬度,高度,顏色格式和位值。 ```c hBitmap = (HBITMAP) LoadImageW(NULL, L"C:\\prog\\slovakia.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); ``` `LoadImageW()`函數從磁盤加載 BMP 圖像。 它返回位圖的句柄。 ```c GetObject(hBitmap, sizeof(bitmap), &bitmap); ``` `GetObject()`函數在提供的`BITMAP`結構中存儲有關位圖的信息。 ```c hdcMem = CreateCompatibleDC(hdc); ``` `CreateCompatibleDC()`函數創建與應用當前屏幕兼容的存儲設備上下文。 ```c oldBitmap = SelectObject(hdcMem, hBitmap); ``` `SelectObject()`函數將一個對象選擇到存儲設備上下文中。 在將位圖用于任何事物之前,必須先將其選擇到存儲設備上下文中。 ```c BitBlt(hdc, 5, 5, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); ``` `BitBlt()`函數執行與像素矩形相對應的顏色數據從指定的源設備上下文到目標設備上下文的位塊傳輸。 ```c SelectObject(hdcMem, oldBitmap); ``` 應用在完成使用新對象的繪制之后,應始終將其替換為原始的默認對象。 ```c DeleteDC(hdcMem); ``` 與存儲設備上下文關聯的資源被釋放。 ![Drawing a bitmap](https://img.kancloud.cn/17/85/178579c7e2c04de44f11eead918886e4_280x220.jpg) 圖:繪制位圖 在 Windows API 教程的這一部分中,我們進行了一些繪制。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看