win32简单的GDI 介绍

       好久没有记录博客了,今天记录下简单的win32对应的GDI吧,上次写博客都过了两个月了,一个是那时候快过年,一个是个人在做些东西,博客没有时间去更新,今天简单记录下win32对应东西吧。本文章是基于  win32程序设计(第5版本),详细的可查阅本书。

      今天简单了解  TEXTMETRIC  结构体对字体的处理:TEXTMETRIC  结构体有20个栏位,这里只简单的介绍7个。

typedef struct tagTEXTMETRIC
{
LONG tmHeight ;
LONG tmAscent ;
LONG tmDescent ;
LONG tmInternalLeading ;
LONG tmExternalLeading ;
LONG tmAveCharWidth ;
LONG tmMaxCharWidth ;
其他结构栏位
}
TEXTMETRIC, * PTEXTMETRIC ;

       对应的变量含义:

程序运行出来会有这样的效果。 

首先我们定义一个后头文件,用来写对应数据。

sysmets.h

#pragma once
#include <windows.h>
#define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))
struct
{
	int Index;
	TCHAR * szLabel;
	TCHAR * szDesc;
}sysmetrics[] =
{
	SM_CXSCREEN, TEXT("SM_CXSCREEN"),
		TEXT("Screen width in pixels"),
	SM_CYSCREEN, TEXT("SM_CYSCREEN"),
		TEXT("Screen height in pixels"),
	SM_CXVSCROLL, TEXT("SM_CXVSCROLL"),
		TEXT("Vertical scroll width"),
	SM_CYHSCROLL, TEXT("SM_CYHSCROLL"),
		TEXT("Horizontal scroll height"),
	SM_CYCAPTION, TEXT("SM_CYCAPTION"),
		TEXT("Caption bar height"),
	SM_CXBORDER, TEXT("SM_CXBORDER"),
		TEXT("Window border width"),
	SM_CYBORDER, TEXT("SM_CYBORDER"),
		TEXT("Window border height"),
	SM_CXFIXEDFRAME,TEXT("SM_CXFIXEDFRAME"),
		TEXT("Dialog window frame width"),
	SM_CYFIXEDFRAME,TEXT("SM_CYFIXEDFRAME"),
		TEXT("Dialog window frame height"),
	SM_CYVTHUMB, TEXT("SM_CYVTHUMB"),
		TEXT("Vertical scroll thumb height"),
	SM_CXHTHUMB, TEXT("SM_CXHTHUMB"),
		TEXT("Horizontal scroll thumb width"),
	SM_CXICON, TEXT("SM_CXICON"),
		TEXT("Icon width"),
	SM_CYICON, TEXT("SM_CYICON"),
		TEXT("Icon height"),
	SM_CXCURSOR, TEXT("SM_CXCURSOR"),
		TEXT("Cursor width"),
	SM_CYCURSOR, TEXT("SM_CYCURSOR"),
		TEXT("Cursor height"),
	SM_CYMENU, TEXT("SM_CYMENU"),
		TEXT("Menu bar height"),
	SM_CXFULLSCREEN,TEXT("SM_CXFULLSCREEN"),
		TEXT("Full screen client area width"),
	SM_CYFULLSCREEN,TEXT("SM_CYFULLSCREEN"),
		TEXT("Full screen client area height"),
	SM_CYKANJIWINDOW,TEXT("SM_CYKANJIWINDOW"),
		TEXT("Kanji window height"),
	SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"),
		TEXT("Mouse present flag"),
	SM_CYVSCROLL, TEXT("SM_CYVSCROLL"),
		TEXT("Vertical scroll arrow height"),
	SM_CXHSCROLL, TEXT("SM_CXHSCROLL"),
		TEXT("Horizontal scroll arrow width"),
	SM_DEBUG, TEXT("SM_DEBUG"),
		TEXT("Debug version flag"),
	SM_SWAPBUTTON, TEXT("SM_SWAPBUTTON"),
		TEXT("Mouse buttons swapped flag"),
	SM_CXMIN, TEXT("SM_CXMIN"),
		TEXT("Minimum window width"),
	SM_CYMIN, TEXT("SM_CYMIN"),
		TEXT("Minimum window height"),
	SM_CXSIZE, TEXT("SM_CXSIZE"),
		TEXT("Min/Max/Close button width"),
	SM_CYSIZE, TEXT("SM_CYSIZE"),
		TEXT("Min/Max/Close button height"),
	SM_CXSIZEFRAME, TEXT("SM_CXSIZEFRAME"),
		TEXT("Window sizing frame width"),
	SM_CYSIZEFRAME, TEXT("SM_CYSIZEFRAME"),
		TEXT("Window sizing frame height"),
	SM_CXMINTRACK, TEXT("SM_CXMINTRACK"),
		TEXT("Minimum window tracking width"),
	SM_CYMINTRACK, TEXT("SM_CYMINTRACK"),
		TEXT("Minimum window tracking height"),
	SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"),
		TEXT("Double click x tolerance"),
	SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"),
		TEXT("Double click y tolerance"),
	SM_CXICONSPACING,TEXT("SM_CXICONSPACING"),
		TEXT("Horizontal icon spacing"),
	SM_CYICONSPACING,TEXT("SM_CYICONSPACING"),
		TEXT("Vertical icon spacing"),
	SM_MENUDROPALIGNMENT, TEXT("SM_MENUDROPALIGNMENT"),
		TEXT("Left or right menu drop"),
	SM_PENWINDOWS, TEXT("SM_PENWINDOWS"),
		TEXT("Pen extensions installed"),
	SM_DBCSENABLED, TEXT("SM_DBCSENABLED"),
		TEXT("Double-Byte Char Set enabled"),
	SM_CMOUSEBUTTONS, TEXT("SM_CMOUSEBUTTONS"),
		TEXT("Number of mouse buttons"),
	SM_SECURE, TEXT("SM_SECURE"),
		TEXT("Security present flag"),
	SM_CXEDGE, TEXT("SM_CXEDGE"),
		TEXT("3-D border width"),
	SM_CYEDGE, TEXT("SM_CYEDGE"),
		TEXT("3-D border height"),
	SM_CXMINSPACING, TEXT("SM_CXMINSPACING"),
		TEXT("Minimized window spacing width"),
	SM_CYMINSPACING, TEXT("SM_CYMINSPACING"),
		TEXT("Minimized window spacing height"),
	SM_CXSMICON, TEXT("SM_CXSMICON"),
		TEXT("Small icon width"),
	SM_CYSMICON, TEXT("SM_CYSMICON"),
		TEXT("Small icon height"),
	SM_CYSMCAPTION, TEXT("SM_CYSMCAPTION"),
		TEXT("Small caption height"),
	SM_CXSMSIZE, TEXT("SM_CXSMSIZE"),
		TEXT("Small caption button width"),
	SM_CYSMSIZE, TEXT("SM_CYSMSIZE"),
		TEXT("Small caption button height"),
	SM_CXMENUSIZE, TEXT("SM_CXMENUSIZE"),
		TEXT("Menu bar button width"),
	SM_CYMENUSIZE, TEXT("SM_CYMENUSIZE"),
		TEXT("Menu bar button height"),
	SM_ARRANGE, TEXT("SM_ARRANGE"),
		TEXT("How minimized windows arranged"),
	SM_CXMINIMIZED, TEXT("SM_CXMINIMIZED"),
		TEXT("Minimized window width"),
	SM_CYMINIMIZED, TEXT("SM_CYMINIMIZED"),
		TEXT("Minimized window height"),
	SM_CXMAXTRACK, TEXT("SM_CXMAXTRACK"),
		TEXT("Maximum draggable width"),
	SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"),
		TEXT("Maximum draggable height"),
	SM_CXMAXIMIZED, TEXT("SM_CXMAXIMIZED"),
		TEXT("Width of maximized window"),
	SM_CYMAXIMIZED, TEXT("SM_CYMAXIMIZED"),
		TEXT("Height of maximized window"),
	SM_NETWORK, TEXT("SM_NETWORK"),
		TEXT("Network present flag"),
	SM_CLEANBOOT, TEXT("SM_CLEANBOOT"),
		TEXT("How system was booted"),
	SM_CXDRAG, TEXT("SM_CXDRAG"),
		TEXT("Avoid drag x tolerance"),
	SM_CYDRAG, TEXT("SM_CYDRAG"),
		TEXT("Avoid drag y tolerance"),
	SM_SHOWSOUNDS, TEXT("SM_SHOWSOUNDS"),
		TEXT("Present sounds visually"),
	SM_CXMENUCHECK, TEXT("SM_CXMENUCHECK"),
		TEXT("Menu check-mark width"),
	SM_CYMENUCHECK, TEXT("SM_CYMENUCHECK"),
		TEXT("Menu check-mark height"),
	SM_SLOWMACHINE, TEXT("SM_SLOWMACHINE"),
		TEXT("Slow processor flag"),
	SM_MIDEASTENABLED, TEXT("SM_MIDEASTENABLED"),
		TEXT("Hebrew and Arabic enabled flag"),
	SM_MOUSEWHEELPRESENT, TEXT("SM_MOUSEWHEELPRESENT"),
		TEXT("Mouse wheel present flag"),
	SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"),
		TEXT("Virtual screen x origin"),
	SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"),
		TEXT("Virtual screen y origin"),
	SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"),
		TEXT("Virtual screen width"),
	SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"),
		TEXT("Virtual screen height"),
	SM_CMONITORS, TEXT("SM_CMONITORS"),
		TEXT("Number of monitors"),
	SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"),
		TEXT("Same color format flag")
};

然后通过,win32基本代码添加数据。

#include <windows.h>
#include "sysmets.h"
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,  HINSTANCE hPrevInstance, 
	LPSTR lpCmdLine,  int nShowCmd)
{
	static TCHAR szAppName[] = TEXT("SysMets1");
	HWND hwnd;           //视窗代号
	MSG msg;             //消息讯息结构
	WNDCLASS wndclass;   //创建windows类
	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("This program requires Windows NT!"),  //显示讯息方块。
			szAppName,MB_ICONERROR);
		return 0;
	}
	//创建windows
	//根据视窗类别建立一个视窗。
	hwnd = CreateWindow(szAppName,  //window class name
		TEXT("The Hello Program"), // 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, nShowCmd);// 在萤幕上显示视窗。
	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)
{
	static int cxChar, cxCaps, cyChar;
	HDC  hdc;        //装置内容代号
	int i;
	PAINTSTRUCT ps;  //绘图结构
	TCHAR szBuffer[10];
	RECT rect;      //矩形结构
	TEXTMETRIC tm;  //文字结构体
	switch (message)
	{
	case WM_CREATE:
		hdc = GetDC(hwnd);   //呼叫 GetDC 取得视窗的装置内容
		GetTextMetrics(hdc, &tm);  //呼叫 GetTextMetrics 取得内定系统字体的文字大小
		cxChar = tm.tmAveCharWidth;  //将平均字元宽度保存在 cxChar 中
		cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) *cxChar / 2;//cxCaps 设定为 cxChar 乘以 150%。
		cyChar = tm.tmHeight + tm.tmExternalLeading;  //将字元的总高度(包括外部间距)保存在 cyChar 中。
		ReleaseDC(hwnd, hdc);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);  //开始绘制视窗。
		//GetClientRect(hwnd, &rect);   //取得视窗显示区域的大小。
		//DrawText(hdc, TEXT("Hello, Windows !"),-1,
		//	&rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); //显示字串。
		for (i = 0; i< NUMLINES; i++)
		{
			TextOut(hdc,0,cyChar*i,
				sysmetrics[i].szLabel,
				lstrlen(sysmetrics[i].szLabel));

			TextOut(hdc, 22 * cxCaps, cyChar * i,
				sysmetrics[i].szDesc,
				lstrlen(sysmetrics[i].szDesc));

			SetTextAlign(hdc, TA_RIGHT | TA_TOP); //向右对齐

			TextOut(hdc, 22 * cxCaps + 40 * cxChar, cyChar * i, szBuffer,
				wsprintf(szBuffer, TEXT("%5d"),
					GetSystemMetrics(sysmetrics[i].Index)));
			SetTextAlign(hdc, TA_LEFT | TA_TOP);
		}
		EndPaint(hwnd, &ps); //结束绘制视窗
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);  //在讯息伫列中插入一个「退出程式」讯息。
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam); //执行内定的讯息处理。
}


cxCaps 等於 cxChar。对於可变宽度字体,cxCaps 设定为 cxChar 乘以 150%。对於可变宽度字体,TEXTMETRIC 结构中的 tmPitchAndFamily 栏位的低位元为 1,对於固定宽度字体,该值为 0。 SYSMETS1 使用这个位元从 cxChar
计算 cxCaps:

cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) *cxChar / 2;

然后通过上面的方式就会发现必须要全部打开,而且没有滚动条可以看下面的东西,如果想添加的话,就必须添加一个卷动列。

卷动列:

 卷动列既有垂直方向的(供上下移动),也有水平方向的(供左右移动)。

话不多说了,开始添加功能,为了方便,这里只变化回调函数对应的东西。

运行后会出现这个卷动条。

 对应改变的代码:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos;
	HDC  hdc;        //装置内容代号
	int i;
	PAINTSTRUCT ps;  //绘图结构
	TCHAR szBuffer[10];
	RECT rect;      //矩形结构
	TEXTMETRIC tm;  //文字结构体
	switch (message)
	{
	case WM_CREATE:
		hdc = GetDC(hwnd);   //呼叫 GetDC 取得视窗的装置内容
		GetTextMetrics(hdc, &tm);  //呼叫 GetTextMetrics 取得内定系统字体的文字大小
		cxChar = tm.tmAveCharWidth;  //将平均字元宽度保存在 cxChar 中
		cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) *cxChar / 2;//cxCaps 设定为 cxChar 乘以 150%。
		cyChar = tm.tmHeight + tm.tmExternalLeading;  //将字元的总高度(包括外部间距)保存在 cyChar 中。
		ReleaseDC(hwnd, hdc);
		//在这里设置卷列表
		//第二个参数 SB_VERT 或者 SB_HORZ,
		SetScrollRange(hwnd, SB_VERT, 0, NUMLINES - 1, FALSE);
		SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
		return 0;
	case WM_SIZE:
		cyClient = HIWORD(lParam);
		return 0;
	case WM_VSCROLL:
		switch (LOWORD(wParam))
		{
		case SB_LINEUP:
			iVscrollPos -= 1;
			break;
		case SB_LINEDOWN:
			iVscrollPos += 1;
			break;
		case SB_PAGEUP:
			iVscrollPos -= cyClient / cyChar;
			break;
		case SB_PAGEDOWN:
			iVscrollPos += cyClient / cyChar;
			break;
		case SB_THUMBPOSITION:
			iVscrollPos = HIWORD(wParam);
			break;
		default:
			break;
		}
		iVscrollPos = max(0, min(iVscrollPos, NUMLINES - 1));
		if (iVscrollPos != GetScrollPos(hwnd, SB_VERT))
		{
			SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
			InvalidateRect(hwnd, NULL, TRUE);
		}
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);  //开始绘制视窗。
		//GetClientRect(hwnd, &rect);   //取得视窗显示区域的大小。
		//DrawText(hdc, TEXT("Hello, Windows !"),-1,
		//	&rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); //显示字串。
		for (i = 0; i< NUMLINES; i++)
		{
			TextOut(hdc,0,cyChar*i,
				sysmetrics[i].szLabel,
				lstrlen(sysmetrics[i].szLabel));

			TextOut(hdc, 22 * cxCaps, cyChar * i,
				sysmetrics[i].szDesc,
				lstrlen(sysmetrics[i].szDesc));

			SetTextAlign(hdc, TA_RIGHT | TA_TOP); //向右对齐

			TextOut(hdc, 22 * cxCaps + 40 * cxChar, cyChar * i, szBuffer,
				wsprintf(szBuffer, TEXT("%5d"),
					GetSystemMetrics(sysmetrics[i].Index)));
			SetTextAlign(hdc, TA_LEFT | TA_TOP); //向左对齐
		}
		EndPaint(hwnd, &ps); //结束绘制视窗
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);  //在讯息伫列中插入一个「退出程式」讯息。
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam); //执行内定的讯息处理。
}

然后在CreateWindow 里面第3个参数,变成:

WS_OVERLAPPEDWINDOW | WS_VSCROLL, // window style

这样写出来的代码,会有滚动条出现,但是没有达到理想的状态,毕竟win32方式处理细节是非常多的,不过也是非常有意思的。

详细细节请产考win32程序设计(第5版本)。

好久没有更新博客了,不能荒废,一点一点都会有所收获。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值