1. 程式人生 > WINDOWS開發 >Windos程式設計,獲取視窗的尺寸

Windos程式設計,獲取視窗的尺寸

前言

學習小甲魚的畫\(sin\)函式的例子,發現最開始建立視窗時cxClient和cyClient不能很好的賦值

WM_SIZE和WM_PAINT

經過我的實踐發現:在剛剛建立視窗時WM_SIZE和WM_PAINT訊息的呼叫順序是隨機的,而且大部分時候先是WM_PAINT
如果cxClient和cyClient需要經過WM_SIZE來初始化,並且WM_PAINT訊息處理中需要使用這兩個變數,那麼第一次的WM_PAINT可能會不正常
這個時候可以選擇手動調整一下視窗的大小,但是使用者體驗肯定是很差的

一種解決方案

由於WM_CREATE訊息肯定優先於WM_PAINT處理,那麼我們可以在處理WM_CREAT時初始化cxClient和cyClient
利用GetClientRect獲取當前的矩形結構

case WM_CREATE:
        GetClientRect(hwnd,&rect);
        cxClient = rect.right-rect.left ;
        cyClient = rect.bottom- rect.top ;
        return 0;

\(sin\)函式程式碼

/* -------------------------------------------------------------------
                    MyWindows.c -- 基本視窗模型
                                《Windows 程式設計(SDK)》視訊教程
--------------------------------------------------------------------*/

#include <Windows.h>
#include <tchar.h>
#include <math.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{


    static TCHAR szAppName[] = TEXT("MyWindows");
    HWND hwnd;//視窗控制代碼

    MSG msg;//訊息結構
    WNDCLASS wndclass;//視窗類結構   


    wndclass.style = CS_HREDRAW | CS_VREDRAW;//視窗型別
    wndclass.lpfnWndProc = WndProc;//指定視窗過程
    wndclass.cbClsExtra = 0;//預留的額外空間
    wndclass.cbWndExtra = 0;//預留的額外空間
    wndclass.hInstance = hInstance;//應用程式的例項控制代碼
    wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);//為所有基於該視窗類的視窗設定一個圖示
    wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);//為所有基於該視窗類的視窗設定一個滑鼠指標
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//	指定視窗背景色
    wndclass.lpszMenuName = NULL;//	指定視窗選單
    wndclass.lpszClassName = szAppName;//指定視窗類名

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL,TEXT("這個程式需要在 Windows NT 才能執行!"),szAppName,MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,//類名
        TEXT("魚C工作室"),//標題
        WS_OVERLAPPEDWINDOW,//風格
        CW_USEDEFAULT,//初始x座標
        CW_USEDEFAULT,//初始y座標
        CW_USEDEFAULT,//初始寬度
        CW_USEDEFAULT,//初始高度
        NULL,//父視窗控制代碼
        NULL,//視窗選單控制代碼
        hInstance,//程式例項控制代碼
        NULL);//建立引數

    ShowWindow(hwnd,iCmdShow);//顯示視窗
    UpdateWindow(hwnd);
    while (GetMessage(&msg,NULL,0))//訊息迴圈
    {
        TranslateMessage(&msg);//翻譯一些鍵盤訊息
        DispatchMessage(&msg);//將訊息傳送給視窗過程
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    static int cxClient,cyClient;
    HDC hdc;//裝置環境控制代碼
    PAINTSTRUCT ps;//繪製結構
    RECT rect;//矩形結構
    //int stx = 0,sty =0;
    POINT apt[1000];
    int num = 1000;
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_CREATE:
        GetClientRect(hwnd,&rect);
        cxClient = rect.right-rect.left ;
        cyClient = rect.bottom- rect.top ;
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd,&ps);//獲得裝置控制代碼

        LineTo(hdc,cxClient,cyClient);
        for (int i = 0; i < num; i++) {
            apt[i].x = i * cxClient / num;
            apt[i].y = (long)(cyClient / 2 * sin(i * 3.1415926 * 2.0 / num)) + cyClient / 2;
        }
        Polyline(hdc,apt,num);
        EndPaint(hwnd,&ps);// 函式標記指定視窗的繪畫過程結束
  
         return 0;

    case WM_DESTROY://視窗關閉
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd,message,wParam,lParam);//交給windows去處理
}