任務目標
設計一個簡單的Windows 窗口程序,在程序窗口內任意位置按下鼠標左鍵,可繪制范圍在10-100之間隨機大小的正方形。並且顯示的正方形用紅色填充。
效果圖

小結
程序先是觸發鼠標左鍵點擊事件,保存鼠標點擊的坐標,並生成隨機數,保存為對角的坐標,由wm_paint先畫出矩形邊框,再將矩形區域進行填充即可。這次實驗主要遇到了兩個問題,第一個是如何畫矩形。我通過百度發現可以用rectangle進行繪圖,就參考模板填寫參數即可。第二個是產生隨機數遇到問題。開始我將srand(time(null))函數放在case內,我發現每次點擊產生的矩形面積是逐漸增大,大到一定值后又從最小值開始遞增。於是我把srand(time(null))放在WndProc函數內、switch外仍然有這個問題。最后我將這個函數放在WinMain內便可以了。我思考發生這個的原因,如果在WndProc內設置種子,每當鼠標點擊一次,會運行一次WndProc,種子便設置為當前時間,因為時間差距不大,導致隨機數初始值相近並遞增。因此需要將種子設置在WinMain下,避免重復設置。
代碼
// sy1v2.cpp : Defines the entry point for the application.
//
#include<windows.h>
#include <MMSYSTEM.H>
#include <iostream>
#pragma comment(lib,"winmm.lib")
#include <time.h>
#include <stdlib.h>
using namespace std;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM) ;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
HWND hwnd;
MSG Msg;
WNDCLASS wndclass;
srand(time(0));
static TCHAR lpszClassName[]=TEXT("窗口");//窗口類名
static TCHAR lpszTitle[]=TEXT("win窗口");//窗口標題名
//窗口類定義
//窗口類定義了窗口的形式與功能 窗口類定義通過給窗口類數據結構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=lpszClassName; //窗口類名為“窗口”
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows XP!"),
lpszClassName, MB_ICONERROR) ;
return 0 ;
}//注冊窗口類
hwnd = CreateWindow(
lpszClassName, //{窗口類的名字}
lpszTitle, //{窗口標題}
WS_OVERLAPPEDWINDOW, //{窗口樣式, 參加下表}
CW_USEDEFAULT,CW_USEDEFAULT, //{位置; 默認的X,Y可以指定為: Integer(CW_USEDEFAULT)}
CW_USEDEFAULT,CW_USEDEFAULT,//{大小; 默認的寬度、高度可以指定為: Integer(CW_USEDEFAULT)}}
NULL, //{父窗口句柄}
NULL, //{主菜單句柄}
hInstance, //{模塊實例句柄, 也就是當前 exe 的句柄}
NULL //{附加參數, 創建多文檔界面時才用到, 一般設為 nil}
); //{返回所創建的窗口的句柄}
ShowWindow (hwnd, nCmdShow) ;//
//消息循環
while(GetMessage(&Msg,NULL,0,0)) //GetMessage()函數是從調用線程的消息隊列中取出一條消息;對於每一個應用程序窗口線程,操作系統都會為其建立一個消息隊列,當我們的窗口有消息時(即所有與這個窗口線程相關的消息),操縱系統會把這個消息放到該線程的消息隊列當中,我們的窗口程序就通過這個GetMessage()函數從自己的消息隊列中取出一條一條具體的消息並進行響應操作。
{
TranslateMessage(&Msg);//對"消息對"的轉化,如對鍵盤的WM_KEYDOWN和WM_KEYUP消息對轉化為WM_CHAR消息,並且將轉換后的新消息投遞到我們的消息隊列中去,這個轉化操作不會影響原來的消息,只會產生一個新的消息。
DispatchMessage(&Msg);//DispatchMessage()函數是將我們取出的消息傳到窗口的回調函數去處理;可以理解為該函數將取出的消息路由給操作系統,然后操作系統去調用我們的窗口回調函數對這個消息進行處理。}
//return Msg.wParam; //消息循環結束 即程序結束時 將信息返回系統
}//
return Msg.wParam;//
}//
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
PAINTSTRUCT ps;//
HDC hdc;//
RECT rect;//
HPEN hPen;
LOGBRUSH logbrush;
HBRUSH hBrush;
int d = 0;
static POINT pt[2];
switch(message){//
case WM_CREATE://
return 0;//
case WM_PAINT:///
hdc = BeginPaint(hwnd, &ps);
hPen = CreatePen(PS_SOLID, 4, RGB(255, 255, 0));
SelectObject(hdc, hPen);
//使用純畫刷
logbrush.lbStyle = BS_SOLID;
//使用陰影畫刷
//logbrush.lbStyle = BS_HATCHED;
logbrush.lbHatch = HS_CROSS;
logbrush.lbColor = RGB(238, 0, 0);
hBrush = CreateBrushIndirect(&logbrush);
//畫矩形
Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
//設置填充區域
SetRect(&rect, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
//填充顏色
FillRect(hdc, &rect, hBrush);
EndPaint(hwnd, &ps);
DeleteObject(hPen);
return 0;//
case WM_LBUTTONDOWN:
pt[0].x=LOWORD(lParam);
pt[0].y=HIWORD(lParam);
//srand(time(0));
d = rand() % 100 + 1;
pt[1].x=pt[0].x+d;
pt[1].y=pt[0].y+d;
InvalidateRect(hwnd,NULL,TRUE);
return 0;
case WM_DESTROY://
PostQuitMessage (0) ;//
return 0 ;//
}//
return DefWindowProc(hwnd,message,wParam,lParam);//
}//
