版权声明:欢迎转载请注明转自方辰昱的博客https://blog.csdn.net/viafcccy https://blog.csdn.net/viafcccy/article/details/85291761
假设我们现在已经创建好窗口
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szWndClassName[] = "hellowin";
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 = szWndClassName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, "注册失败",
"错误", MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szWndClassName, // window class name
"窗口标题", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0)) //消息队列
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ; //WM_QUIT
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT ("在屏幕中心输出文字"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
我们可以直接copy“创建窗口”中的框架
我们可以使用绘图函数进行绘图 需要填写的参数可以右键 转到定义去看
因此我们只需要在switch中添加case来监听鼠标消息即可 也就是对于鼠标消息做出反应
鼠标消息
WM_LBUTTONDOWN WM_RBUTTONDOWN WM_LBUTTONUP WM_RBUTTONUP WM_LBUTTONDBLCLK WM_RBUTTONDBLCLK WM_MOUSEMOVE 对于以上所有鼠标消息,wParam值指示Shift和Ctrl键或鼠标键的状态,可以用位屏蔽法测试(MK前缀代表鼠标键);lParam值为鼠标的位置,其中低位字为x坐标,高位字为y坐标
这样我们完成了鼠标消息响应的测试
下面来完成我们的画板
是用BeginPaint还是GetDC?
均可以获得设备描述表句柄。区别在于:
BeginPaint是“被动的”,仅能在无效区域绘图,并使之有效; GetDC是“主动的”,程序需要时就可在客户区任意位置绘图。 BeginPaint会通知系统之前的无效区域已变为有效; GetDC和是否为有效区域无关,不会清除消息队列中的 WM_PAINT消息。
我们制作一个画板
需要监听鼠标移动 同时如果有左键按下呢么就画上线条
如果使用像素点构成线条
因为消息响应原因只会出现断点
我们如果把点连成线即可
#include <windows.h>
typedef struct
{
int x;
int y;
}Point;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szWndClassName[] = "hellowin";
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 = szWndClassName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, "注册失败",
"错误", MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szWndClassName, // window class name
"绘图板", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0)) //消息队列
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ; //WM_QUIT
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
static Point prePoint; //前一个点
static HPEN hPens[3]; //定义一个句柄数组
static int index; //用来遍历句柄
switch (message)
{
case WM_CREATE:
{
hPens[0]=CreatePen(PS_SOLID,5,RGB(255,0,0));
hPens[1]=CreatePen(PS_SOLID,10,RGB(0,255,0));
hPens[2]=CreatePen(PS_SOLID,15,RGB(0,0,255));
}
return 0;
case WM_KEYDOWN:
{
if(VK_RETURN==wParam)
{
InvalidateRect(hwnd,NULL,TRUE); //将窗口无效化
}
}
return 0;
case WM_MOUSEMOVE:
{
if(MK_LBUTTON & wParam) //鼠标左键被摁下
{
Point point;
point.x=LOWORD(lParam);
point.y=HIWORD(lParam);
hdc = GetDC(hwnd);
SelectObject (hdc, hPens[index]) ;
MoveToEx(hdc,prePoint.x,prePoint.y,NULL);
LineTo(hdc,point.x,point.y);
ReleaseDC(hwnd,hdc);
prePoint=point;
}
}
return 0;
case WM_LBUTTONDOWN: //获取鼠标的坐标
{
int x=LOWORD(lParam);
int y=HIWORD(lParam);
prePoint.x=x;
prePoint.y=y;
}
return 0;
case WM_RBUTTONDOWN: //换颜色、粗度
{
index++;
if(index==3)index=0;
}
return 0;
case WM_DESTROY: //释放资源
DeleteObject(hPens[0]);
DeleteObject(hPens[1]);
DeleteObject(hPens[2]);
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}