更新时间:2015-12-17 17:15:29浏览次数:1+次
CreatePen(PS_SOLID,6,RGB(255,0,0));//返回一个画笔句柄,直接传给了函数
我们划线使用函数MoveToEx将当前画笔移动到线的开始处,也就是我们鼠标左键单击的位置,这个位置就在WM_LBUTTONDOWN消息下记录下来,因为这个位置要在其他消息中使用,所以设置为了静态的变量。通过GET_X_LPARAM和GET_Y_LPARAM宏从WM_LBUTTONDOWN消息的lParam参数提取坐标。代码如下:MoveToEx(hdc,ptOld.x,ptOld.y,NULL);//将当前位置移动到上一次结束的位置,虽然系统会自动更新,但是第一次我们自己设置一下,可以从单击的位置开始画
因为我们画画是移动鼠标,移动的过程会产生很多的鼠标移动消息,我们要将接受到的所有的鼠标位置用直线连接起来。所以,这个静态变量我取名为了ptOld,因为每次接收到鼠标移动消息后,就将上一个点和当前的点连接后,将当前点设置为上一个点的坐标,以便后面的点与这个点连接。这个就是不断的往前推进迭代了。ptOld.x = GET_X_LPARAM(lParam);
ptOld.y = GET_Y_LPARAM(lParam);
我们提供了擦除划线的功能,这个实现分析见文章《SetPixel和GetPixel函数实现自由画图和橡皮擦功能》。为了更快的擦除所有的线,就处理了键盘消息WM_KEYDOWN,只要单击了键盘的按键,就让客户区失效导致重绘,进而就擦掉了客户区画的内容了。对于使客户区失效导致重绘的函数InvalidateRect的详细分析,请看《InvalidateRect是否删除背景效果分析以及实现下划线删除线》和《InvalidateRect无效矩形的图文分析和在字符串中移动光标》。#include "windows.h"
#include <Windowsx.h>//GET_X_LPARAM,GET_Y_LPARAM宏需要这个头文件
#include <tchar.h>
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static bool bisPaint=false;
static bool bisClear=false;
TCHAR Info[100]=_T("【C++技术网http://www.cjjjs.com】");
int iRed,iGreen,iBlue;
static POINT ptOld;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);//会清除无效矩形
TextOut(hdc,0,10,Info,lstrlen(Info));
EndPaint(hwnd,&ps);
return 0;
case WM_LBUTTONDOWN:
bisPaint=true;//开始作画
ptOld.x = GET_X_LPARAM(lParam);
ptOld.y = GET_Y_LPARAM(lParam);
return 0;
case WM_LBUTTONUP:
bisPaint=false;//松开鼠标,结束绘画
return 0;
case WM_RBUTTONDOWN:
bisClear=true;
return 0;
case WM_RBUTTONUP:
bisClear=false;
return 0;
case WM_KEYDOWN:
InvalidateRect(hwnd,NULL,TRUE);
return 0;
case WM_MOUSEMOVE:
if(bisPaint)//如果按着鼠标时,表示在作画,因此可以开始绘制
{
hdc = GetDC(hwnd);
MoveToEx(hdc,ptOld.x,ptOld.y,NULL);
SelectObject(hdc,CreatePen(PS_SOLID,6,RGB(255,0,0)));
LineTo(hdc,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));
ptOld.x = GET_X_LPARAM(lParam);
ptOld.y = GET_Y_LPARAM(lParam);
ReleaseDC(hwnd,hdc);
}
if(bisClear)
{
//-擦除绘图
hdc = GetDC(hwnd);
COLORREF clr = GetPixel(hdc,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));//获得当前像素颜色
int red = GetRValue(clr);
int green = GetGValue(clr);
int blue = GetBValue(clr);
if(red==0&&green==0&&blue==0)return 0;//-如果本身就是背景的黑色,就不用擦除
//if(clr==0)return 0;//更快速的判断,黑色的三个分量都是0,合起来还是0
COLORREF clrClear = RGB(0,0,0);//合成创建一个黑色
//循环设置25个像素大小的橡皮擦,从中心点(当前鼠标光标所在的点)向四周延伸两个像素
for (int i=-10;i<=10;i++)
{
for (int j=-10;j<=10;j++)
{
SetPixel(hdc,GET_X_LPARAM(lParam)+i,GET_Y_LPARAM(lParam)+j,clrClear); //-单像素
}
}
ReleaseDC(hwnd,hdc);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
if(!RegisterClass(&wndClass))
{
return 0;
}
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,440,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
相关资讯