windows程序设计(9):简单的GDI对象

第一个要介绍的是画笔。

通常我们理解的划线,应该是在划线函数中指明,我这条线画出来应该有多宽,线的类型是什么(比如虚线,点划线,实现)等等。而且很多地方就是这样做的,比如开源计算机视觉库OpenCV,Matlab等等中就是这样。但是Windows程序设计却是另一种思路:我先设计一个画笔,这根笔决定了我划线的颜色,粗细,线型等等。然后选择这根笔,最后划线。这样做好处其实也很多,大家如果习惯了word或者visio里面的绘图的话,也不难理解这样做的方便之处。

举一个例子:

#include <windows.h>
#include <math.h>
#define NUM 1000
#define TWOPI (2*3.14159)

#define LOGWIDE 4000
#define LOGHIGH 3000

LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,		//当前实例句柄
				   HINSTANCE hPrevInstance, //先前实例句柄
				   LPSTR lpCmdLine,			//命令行
				   int iCmdShow)			//显示状态
{
	static TCHAR szAppName[] = TEXT("画图");
	//窗口句柄
	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))
	{
		return -1;
	}

	//创建窗口
	hwnd = CreateWindow(szAppName,				//窗口类的名称,必须是已经注册的
						TEXT("我的画图"),		//窗口标题
						WS_OVERLAPPEDWINDOW,	//窗口风格
						CW_USEDEFAULT,			//X坐标
						CW_USEDEFAULT,			//Y坐标
						CW_USEDEFAULT,			//宽度
						CW_USEDEFAULT,			//高度
						NULL,					//父窗口句柄
						NULL,					//菜单窗口句柄
						hInstance,				//高级版本的windos忽略
						NULL);					

	//显示窗口
	//ShowWindow(hwnd,SW_SHOWNA);
	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;
	HPEN hPen;
	PAINTSTRUCT ps;
	int i;
	static int cxClient,cyClient;
	POINT apt[NUM];
	switch(message)
	{
	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);


		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd,&ps);

		for(i = 0; i < 256;i++)
		{
			/*
			//创建画笔:参数为:画笔风格,画笔宽度,画笔颜色
			hPen = CreatePen(PS_SOLID,i,RGB(i,0,0));
			SelectObject(hdc,hPen);
			MoveToEx(hdc,300,200,NULL);
			LineTo(hdc,300,500);
			DeleteObject(hPen);
			Sleep(10);
			*/
			
			MoveToEx(hdc,		0,cyClient/2,NULL);
			LineTo	(hdc,cxClient,cyClient/2);
			MoveToEx(hdc,		0,cyClient/2,NULL);
			//画正弦曲线
			for(i = 0; i < NUM;i++)
			{
				hPen = CreatePen(PS_SOLID,(int)(i/10),RGB((int)(i/4),0,0));
				SelectObject(hdc,hPen);
				apt[i].x = i * cxClient / NUM;
				apt[i].y = (int)(cyClient /2*(1-sin(TWOPI *i/NUM)));
				LineTo(hdc,apt[i].x,apt[i].y);
				DeleteObject(hPen);
				//Sleep(10);
			}
		}

		EndPaint(hwnd,&ps);
		return 0;


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


 

还是画正弦曲线,但是每画一笔,我都要改变线的宽度和颜色,其中(i/10)和(i/4)仅仅是为了让宽度和颜色的变化不会太快。

然后要介绍的是关于写字方面的内容DrawText。

首先要明白,你在窗口上写字DrawText时,要注意3中颜色:第一是背景的颜色,这通过wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH);改变;第二是你写的那些字颜色,通过SetTextColor(hdc,RGB(255,0,0));改变;第三是你写的那些字的背景颜色,就是说你写的那些字,占用了一个个方格,这些格子的背景是什么颜色的,这通过SetBkColor(hdc,RGB(128,128,128));来改变。但在通常情况下,我们把字的背景设为透明SetBkMode(hdc,TRANSPARENT);,让它随着窗口颜色变化而变化。下面我们看看这个简单的程序:

#include <windows.h>
#include <math.h>



LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,		//当前实例句柄
				   HINSTANCE hPrevInstance, //先前实例句柄
				   LPSTR lpCmdLine,			//命令行
				   int iCmdShow)			//显示状态
{
	static TCHAR szAppName[] = TEXT("画图");
	//窗口句柄
	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.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH);
	//菜单:暂时没有
	wndclass.lpszMenuName  = NULL;
	//窗口类名
	wndclass.lpszClassName = szAppName;

	//注册窗口
	if(!RegisterClass(&wndclass))
	{
		return -1;
	}

	//创建窗口
	hwnd = CreateWindow(szAppName,				//窗口类的名称,必须是已经注册的
						TEXT("我的画图"),		//窗口标题
						WS_OVERLAPPEDWINDOW,	//窗口风格
						CW_USEDEFAULT,			//X坐标
						CW_USEDEFAULT,			//Y坐标
						CW_USEDEFAULT,			//宽度
						CW_USEDEFAULT,			//高度
						NULL,					//父窗口句柄
						NULL,					//菜单窗口句柄
						hInstance,				//高级版本的windos忽略
						NULL);					

	//显示窗口
	//ShowWindow(hwnd,SW_SHOWNA);
	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;
	HPEN hPen;
	PAINTSTRUCT ps;
	int i;
	static int cxClient,cyClient;
	RECT rect;
	switch(message)
	{
	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);


		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd,&ps);
		//设置背景颜色
		//SetBkColor(hdc,RGB(128,128,128));
		//将背景模式:透明
		SetBkMode(hdc,TRANSPARENT);
		//将背景模式:不透明
		//SetBkMode(hdc,OPAQUE);
		//设置字的颜色
		SetTextColor(hdc,RGB(255,0,0));
		//获取客户区坐标
		GetClientRect(hwnd,&rect);  
		
		DrawText(hdc,TEXT("Hello, Windows7!"),-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);
}


 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值