windows程序设计之GDI简介

      最近在做一个有关激光笔的小项目,和学长们一起做的。里面还有硬件成份,现在因为才开始做,我主要做软件上面的东西,当然技术含量是很少的抓狂···诶,学了一年左右了,水平还是没很大长进啊~~~大哭刚刚C入门,SDK也只能说勉强算是入门了吧。。。项目里面有一部分是要绘制出来鼠标的移动轨迹的,我就去重新看了下GDI,发现自己以前没写过这些东西,印象就是不深刻啊,于是就温习了下。重新看了下<<windows程序设计>>和<<API函数,接口编程实例>>,ctrl+c和ctrl+v出来下面个实验品,然后做了些笔记,我还是记得学长讲得那句话:博客就是用来记录自己成长的地方。无论有什么学到的,都可以写上来,无论含量高不高,总能在自己以后有一天需要的时候想起来,并且找到,这大概和老师说的好记性不如让笔头差不多吧~~~

下面是自己一些简单的总结:

windows GDI绘图
Graphics Device Interface:图形设备接口
GDI是GraphicsDeviceInterface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。
在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。GDI的出现使程序员无需要关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。

1.资源使用
 // 初始的颜色
 BYTE bRed  = 0;
 BYTE bGreen  = 0;
 BYTE bBlue = 0;
 // 笔的颜色 正黑
 COLORREF cPen = RGB(bRed, bGreen, bBlue);
 //画笔的设置
 HPEN CreatePen(
  __in  int fnPenStyle,
  __in  int nWidth,
  __in  COLORREF crColor
 );
 HPEN hpen;
 hpen = CreatePen(PS_SOLID, 10, cPen);    //画笔基本属性
 
 //画刷的设置
 HBRUSH hbrush;
 COLORREF cBrush = RGB(233, GetGValue(cPen),255);
 hbrush = CreateSolidBrush(cBrush);
 // 释放资源
 DeleteObject(hpen);
 DeleteObject(hbrush);


2.获取DC。获取了DC就相当于获取了绘画的资格。
 HDC hDC = GetDC(hWnd);//参数是NULL时获取的是整个显示器的DC,若是句柄就是指定窗口的DC。


3.将DC设置成对象目标句柄。将图形对象选入DC中,这样DC中原有的类型图形对象就会被新的对象替换。
 SelectObject(hDC, hpen);
 SelectObject(hDC, hbrush);
 这样绘画的时候就可以改变默认的DC属性。


4.绘画区域的变化 
 GetClientRect(hWnd, &rect);这里获取的是客户区域的大小,是以客户区左上角为坐标原点进行创建的。因此比如在处理WM_MOUSEMOVE等鼠标消息的时候,传进来的lParam参数中包含的坐标也是相对于客户端的。要想转化成屏幕坐标可以用下面的方法:
    //转换窗口有效区为屏幕座标
   POINT point;
   point.x = 0, point.y = 0;
   ClientToScreen(hWnd,&point);
 你要是想把光标限制在客户区内,可以这样:
    //将光标限定在窗口有效区内
   rect.top = point.y;
   rect.left = point.x;
   rect.bottom += rect.top;
   rect.right += rect.left;
    ClipCursor(&rect);  //rect一定要是屏幕座标
 下面是获取屏幕坐标的函数
   POINT pt;
   GetCursorPos(&pt);
 这里获取的坐标就是相对屏幕左上角的坐标。若是要转化成客户区坐标可以用
   ScreenToClient(hWnd,&point);


5.绘制线条
 移到指定的点

 BOOL MoveToEx(
  __in   HDC hdc,
  __in   int X,
  __in   int Y,
  __out  LPPOINT lpPoint //Pointer to a POINT structure that receives the previous current position. If this parameter is a          //NULL pointer, the previous position is not returned.
 );
 //画直线
 BOOL LineTo(
   __in  HDC hdc,
   __in  int nXEnd,
   __in  int nYEnd
 );
 // 绘制矩形
 BOOL Rectangle(
  __in  HDC hdc,
  __in  int nLeftRect,
  __in  int nTopRect,
  __in  int nRightRect,
  __in  int nBottomRect
 );
 //绘制椭圆(圆)
 BOOL Ellipse(
  __in  HDC hdc,
  __in  int nLeftRect,
  __in  int nTopRect,
  __in  int nRightRect,
  __in  int nBottomRect
);
 //绘制矩形
 BOOL Rectangle(
  __in  HDC hdc,
  __in  int nLeftRect,
  __in  int nTopRect,
  __in  int nRightRect,
  __in  int nBottomRect
 );
 //绘制圆角矩形
 BOOL RoundRect(
  __in  HDC hdc,
  __in  int nLeftRect,
  __in  int nTopRect,
  __in  int nRightRect,
  __in  int nBottomRect,
  __in  int nWidth,
  __in  int nHeight
 );


下面是我修改的一个绘制鼠标轨迹的小程序

#include <windows.h>
#include <stdio.h>

#define MAXGUIDESEGMENTS 1000
#define MyAlloc(dwSize) HeapAlloc(GetProcessHeap(),0,dwSize)
#define MyFree(lpMem) HeapFree(GetProcessHeap(),0,lpMem);

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL GetGuideLine(HWND hWnd, LPPOINT *lpPoint, LPDWORD lpdwNumPts);

LONG clsCur;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT ("LineDemo") ;
	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 ("Program requires Windows NT!"), 
			szAppName, MB_ICONERROR) ;
		return 0 ;
	}

	hwnd = CreateWindow (szAppName, TEXT ("Line Demonstration"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL) ;


	ShowWindow (hwnd, iCmdShow) ;
	UpdateWindow (hwnd) ;

	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hDC = NULL ;
	static LPPOINT lpRed = NULL;
	static DWORD dwRed = 0;
	switch (message)
	{
	case WM_CREATE:
		hDC = GetDC(hwnd);
		break;

	case WM_LBUTTONDOWN:
		//取得窗口有效区
		RECT rect;
		GetClientRect(hwnd,&rect);

		//转换窗口有效区为屏幕座标
		POINT point;
		point.x = 0, point.y = 0;
		ClientToScreen(hwnd,&point);
		rect.top = point.y;
		rect.left = point.x;
		rect.bottom += rect.top;
		rect.right += rect.left;

		ClipCursor(&rect);  //rect一定要是屏幕座标

		if (!clsCur) {
			clsCur = GetClassLong(hwnd,GCL_HCURSOR);  //取当前窗口的光标
		}
		SetClassLong(hwnd,GCL_HCURSOR,NULL);  //设置当前窗口的光标为NULL
		SetCursor(LoadCursor(NULL, IDC_CROSS)); //设置当前光标为十字形
		
		GetGuideLine(hwnd, &lpRed, &dwRed);

		break;
	case WM_DESTROY:
		if (lpRed)
			MyFree(lpRed);
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BOOL GetGuideLine(HWND hWnd, LPPOINT *lpPoint, LPDWORD lpdwNumPts)
{
	MSG msg;
	HDC hDC = GetDC(hWnd);
	BOOL bFirstTime = TRUE;
	DWORD dwPos = 0;
	RECT rect;
	static HPEN  hpen;

	hpen = CreatePen(PS_SOLID,3, RGB(0,255,0));		
	SelectObject(hDC,hpen);

	GetClientRect(hWnd, &rect);
	// 为点数组分配空间
	*lpPoint = (LPPOINT)MyAlloc(MAXGUIDESEGMENTS * sizeof(POINT));
	SetCapture(hWnd);	// 设置鼠标捕获器
	// 将客户区填充为白色                
	GetClientRect(hWnd, &rect);
	PatBlt(hDC, 0, 0, rect.right, rect.bottom, WHITENESS);

	while(1)
	{
		// 过滤所有鼠标消息
		WaitMessage();
		if (PeekMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE))
		{
			// 判断是否在客户区中
			if ((LOWORD(msg.lParam) < rect.right) && (HIWORD(msg.lParam) < 
				rect.bottom))
			{
				// 是否第一次收到消息
				if (bFirstTime)
				{
					bFirstTime = FALSE;
					// 如果是第一次将笔的起点移动到鼠标点击的位置
					MoveToEx(hDC, LOWORD(msg.lParam), HIWORD(msg.lParam), 
						NULL);
				}
				// 是否达到了最大点数
				if (dwPos < MAXGUIDESEGMENTS)
				{
					// 鼠标的移动会产生鼠标消息,每收到一次消息保存一个点			
					(*lpPoint)[dwPos].x = LOWORD(msg.lParam);
					(*lpPoint)[dwPos].y = HIWORD(msg.lParam);
					// 绘制到鼠标所在的点
					LineTo(hDC, (*lpPoint)[dwPos].x, (*lpPoint)
						[dwPos].y);
					dwPos++;
				}
			}	
		}
		if (msg.message == WM_RBUTTONDOWN)
		{
			ClipCursor(NULL);
			SetClassLong(hWnd,GCL_HCURSOR, clsCur);
			SetCursor((HCURSOR)clsCur);	
			break;
		}
		else
			continue;
	}

	*lpdwNumPts = dwPos;
	ReleaseDC(hWnd, hDC);
	ReleaseCapture();
	DeleteDC( hDC );

	return TRUE;
}


最近的时间越来越紧啊···专业课越来越难,自己课余学计算机的时间也越来越少,诶····真是后后悔自己没去计算机专业额····

呼呼,,,,不过事在人为,努力就好!昨天看到一句比较好的话:一个优秀的程序员:勤奋+执着!我看着很有感触,有时

时觉得自己花那么多时间面对代码,是否值得···不过我想有付出就会有回报的!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值