笔记【图书管理系统】开发之客户端界面设计 (TBBUTTON,IMAGELIST,BITMAP,兼容DC)

要设计这样一个界面,这篇主要讲五个按钮的设置以及下面背景图片的载入

首先5个按钮

一、设置工具栏以及工具栏按钮

1.工具栏的设置:

HWND hToolbar;

CreateWindowEx(

 0,        //窗口扩展风格

 TOOLBARCLASSNAME,       //窗口类名称

 "TOOLBAR",            //窗口名称
WS_VISIBLE | WS_CHILD ,        //窗口格式
0,0,0,0,              //窗口的位置以及大小
hWnd,              //父窗口句柄
NULL,              //窗口菜单句柄
hInstance,            //程序实例句柄
NULL)              //创建参数

 

这个TOOLBARCLASSNAME是windows的用于创建一个包含一些菜单栏命令按钮的工具栏,文档里是这么说的:Creates toolbars. These controls contain buttons that carry out menu commands.

2.然后创建五个BUTTON,这里涉及到TBBUTTON结构:这是一个在工具栏中定义按钮相关信息的结构(当然,要使用这些控件API要首先包含Commctrl.h)

typedef struct {
  int       iBitmap;   //从0开始的按钮图标索引
  int       idCommand;    //按钮按下时发送的命令
  BYTE      fsState;   //按钮状态
  BYTE      fsStyle;   //按钮风格
#ifdef _WIN64
  BYTE      bReserved[6];
#else 
#if defined(_WIN32)
  BYTE      bReserved[2];
#endif 
#endif 
  DWORD_PTR dwData;   //用户自定义数据
  INT_PTR   iString;   //从0开始的按钮标签索引
} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;

这是在msdn上查到的结构定义。

fsState:

TBSTATE_CHECKED
 
当该button是TBSTYLE_CHECK风格的且被选中
 
 
TBSTATE_ELLIPSES
 
button的文本被切断,用省略号显示
 
 
TBSTATE_ENABLED
 
button可用,若这个状态没有被选中,则该按钮是灰色不可用的状态
 
 
TBSTATE_HIDDEN
 
button不可见且不能接收用户输入
 
 
TBSTATE_INDETERMINATE
 
被灰化的
 
 
TBSTATE_MARKED
 
该按钮被标注
 
 
TBSTATE_PRESSED
 
该按钮被按下
 
 
TBSTATE_WRAP
 
该按钮后面跟一个换行符,必须与TBSTATE_ENABLED状态一同使用
 



这里只需要设置它的位图索引,工具的命令,按钮状态,按钮风格以及按钮标签索引

1)要设置位图索引,首先要将图标载入

先创建Imagelist:


  

HIMAGELIST ImageList_Create(
   int  cx,     //每个图标的宽,以像素为单位
   int  cy,     //每个图标的高,以像素为单位
   UINT flags,     //要创建的ImageList的模式
   int  cInitial,     //ImageList中image的数量
   int  cGrow      //当系统需要时,图像列表可以增长的图像数量
);


这里的flags:

ILC_COLOR 缺省模式,默认=ILC_COLOR4。老版本的系统是ILC_COLORDDB使用设备依赖位图。
ILC_COLOR4 4位DIB位图,表示生成的位图每个像素是由4位组成,也就是16色位图。
ILC_COLOR8 同上,8位位图,256色。
——上面2个都要用到调色板。
ILC_COLOR16 16 位DIB(32/64k 色) 位图。
ILC_COLOR24 24 位真彩色位图。
ILC_COLOR32 32位真彩,显示效果跟ILC_COLOR24位一样,多了一个Alpha通道,记录透明度,方便操作。
ILC_COLORDDB 设备依赖位图,表示颜色位跟设备(操作系统记录着)相关。
ILC_MASK 使用掩膜,当前ImageList使用2个位图,如果指定了一个单色位图,就将其做为掩膜,掩膜是用来透明的,就是显示时候不绘制背景——这样看起来效果很真实,xp操作系统桌面的图标就是这个效果。
参数写0,就为ILC_COLOR。默认值。


位图位数越大,色彩就越鲜艳。


设置图片的背景色并将ImageList信息传给工具栏

bkColor = GetSysColor(COLOR_3DFACE);  //先获取系统的背景色,COLOR_3DFACE表示3D阴影化对象的正面颜色

ImageList_SetBkColor(hImagelist,bkColor); //将图片背景色设置为默认系统背景色

SendMessage(hToolbar,TB_SETIMAGELIST,0,(LPARAM)(HIMAGELIST)hImagelist); //将Imagelist信息传给工具栏


将图标装载入ImageList中

将已经载入项目资源的icon转为其指针(把数字转换为指针类型),然后获取该icon资源的资源句柄


这里是这样用:

hIcon = LoadIcon ( hInstance,MAKEINTRESOURSE ( ID_ICON ) ) ;

将该图片资源载入ImageList:

int ImageList_AddIcon(  //返回值是ImageList中该图片的索引值
   HIMAGELIST himl,   
   HICON      hicon
);


2)然后设置TBBUTTON结构的属性

3)向工具栏添加按钮并做相应设置

SendMessage(hToolbar , TB_ADDBUTTONS , add_Num , (LPARAM)(TBBUTTON)tbt);

//设置按钮大小

SendMessage(hToolbar, TB_SETBUTTONSIZE, 0,MAKELONG ( cx , cy ) );

//设置按钮大小自动调节

SendMessage(hToolbar,TB_AUTOSIZE,0,0);


二:绘制主页面背景


1.创建缓存DC并设置

因为这里要用到CreateCompatibleDC,所以首先了解下为什么要用这个函数创建一个缓存DC。

 首先明白DC的含义,Windows不允许程序员直接访问硬件,它对屏幕的操作是通过环境设备,也就是DC来完成的。屏幕上的每一个窗口都对应一个DC,可以把DC想象成一个视频缓冲区,对这这个缓冲区的操作,会表现在这个缓冲区对应的屏幕窗口上。如果连续在窗口上进行持续的操作,则会造成窗口闪烁,为了减轻这种闪烁的现象,则使用兼容DC,这个DC不直接对应窗口,它将图片大小像素等属性按照修正后的值“传递”给资源句柄DC,则能实现一次性刷新,避免窗口的闪烁,且无论选用背景图片大小是否和主界面客户区一直都能按照同比例伸缩。

HDC CreateCompatibleDC(HDC hdc);

如果该函数传入值为空,那么就创建应用程序窗口的兼容DC,如果传入DC参数,那么就创建与该DC的兼容DC。但是兼容DC在创建的时候,只有1*1像素的尺寸,这明显太小了,因此我们可以通过SelectObject来选择一个位图,作为兼容DC的可见区域。

HDC memDC;

HBITMAP bmp;

BITMAP mBitmap;

memDC = CreateCompatibleDC(hdc);       //创建缓存
bmp = LoadBitmap(g_hInstance,MAKEINTRESOURSE(ID_BITMAP));  //获取图片到bmp位图句柄中
GetObject(bmp,sizeof(BITMAP),&mBitmap);       //获取位图的信息,包括长度宽度等存入                //BITMAP结构的mBitmap中
SelectObject(memDC,bmp);         //将这个位图句柄选入缓存DC中

BITMAP结构:

typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数
LONGbiWidth; // 位图的宽度,以像素为单位
LONGbiHeight; // 位图的高度,以像素为单位
WORD biPlanes; // 目标设备的级别,必须为1
WORD biBitCount// 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; // 位图的大小,以字节为单位
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
DWORD biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;


2.将缓存的内容(兼容DC中的内容)交给资源句柄来绘制图片

对于双缓冲视图显示图像,有两种方法:

StretchBlt:函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩。也即是将内存中的位图拷贝到屏幕上,并且可以根据屏幕画图区的大小来进行伸缩,适应响应的屏幕(或图像控件)

BOOL StretchBlt(
  HDC hdcDest,      //目标环境句柄
  int nXOriginDest, //指定目标矩形左上角逻辑x坐标
  int nYOriginDest, //指定目标矩形左上角逻辑y坐标
  int nWidthDest,   //指定目标矩形宽逻辑单位
  int nHeightDest,  //指定目标矩形高逻辑单位
  HDC hdcSrc,       //原设备环境句柄
  int nXOriginSrc,  //源矩形左上角逻辑x坐标
  int nYOriginSrc,  //源矩形左上角逻辑y坐标
  int nWidthSrc,    //源矩形宽逻辑单位
  int nHeightSrc,   //源矩形高逻辑单位
  DWORD dwRop);    //指定要进行的光栅操作
光栅操作类型:
DSTINVERT:表示使目标矩形区域颜色取反。
MERGECOPY:表示使用布尔型的AND(与)操作符将源矩形区域的颜色与特定模式组合一起。
MERGEPAINT:通过使用布尔型的OR(或)操作符将反向的源矩形区域的颜色与目标矩形区域的颜色合并。
NOTSRCCOPY:将源矩形区域颜色取反,再拷贝到目标矩形区域。
NOTSRCERASE:使用布尔类型的OR(或)操作符组合源和目标矩形区域的颜色值,然后将合成的颜色取反。
PATCOPY:将特定的模式拷贝到目标 位图上。
PATPAINT:通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模式的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并。
PATINVERT:通过使用XOR(异或)操作符将源和目标矩形区域内的颜色合并。
SRCAND:通过使用AND(与)操作符来将源和目标矩形区域内的颜色合并。
SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。 (最常使用)
SRCERASE:通过使用AND(与)操作符将目标矩形区域颜色取反后与源矩形区域的颜色值合并。
SRCINVERT:通过使用布尔型的XOR(异或)操作符将源和目标矩形区域的颜色合并。
SRCPAINT:通过使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并。
WHITENESS:使用与物理 调色板中索引1有关的 颜色填充目标矩形区域。(对于缺省物理调色板来说,这个颜色就是白色)。

BitBlt:该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。不会对原来的位图进行拉伸或压缩,只会根据我们给定的nWidth,nHeight 值来决定该有多少部分进行显示.

比上面StretchBlt少了nWidthSrc,nHeightSrc两个参数

这里我们将缓存内容交给资源句柄来绘制的语句:

StretchBlt(hdc,0,0,CxClient,CyClient,memDC,0,0,mBitmap.bmWidth,map.bmHeight,SRCCOPY);


三。该模块完整代码

BOOL CALLBACK ClientDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	char marks[5][20] = { "图书信息","图书入库","销售查询","系统配置","系统退出" };
	HWND hToolbar;				//工具栏句柄
	u_int i;					//循环语句迭代器
	int ImageID[5];				//存放ImageList中小图标标志
	HIMAGELIST him;				//用来存放image或者icon,在本程序中使用它向工具栏添加图片
	u_long bkColor;				//存放系统默认颜色
	TBBUTTON tbs[5];			//存放五个工具栏子项的相关属性结构
	HDC hdc;					//设备环境句柄
	HDC memDC;
	BITMAP mBitmap;				//位图文件属性的结构
	HBITMAP bmp;				//位图文件句柄
	RECT rect;
	int Width;
	int Height;
	int x;
	PAINTSTRUCT ps;				//窗口中与绘画相关信息的结构
	switch (message)
	{
	case WM_INITDIALOG:
		//设定窗口的位置
		SetWindowPos(hDlg, HWND_TOP, 700, 300, 0, 0, SWP_NOSIZE);
		//在主界面中设置工具栏
		hToolbar = CreateWindowEx(WS_EX_APPWINDOW, TOOLBARCLASSNAME, "toolbar",
			WS_VISIBLE | WS_CHILD /*| CCS_TOP*/, 0, 0, 120, 120, hDlg, NULL, g_hInstance, NULL);
		//向空工具栏传递按钮数据的大小信息
		SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
		him = ImageList_Create(24, 24, ILC_COLOR24, 5, 0);
		bkColor = GetSysColor(COLOR_3DFACE);		//获取系统背景色
		ImageList_SetBkColor(him, bkColor);			//将图片的背景色设定为默认的背景色
		//向工具栏传递当前使用的ImageList信息
		SendMessage(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)(HIMAGELIST)him);
		//将此图标装载入ImageList中
		for (i = 0; i < 5; i++)
		{
			//将IMAGELISt结构填充并加载图标资源ID
			ImageID[i] = ImageList_AddIcon(him, LoadIcon(g_hInstance,
				MAKEINTRESOURCE(IDI_ICON1 + i)));
		}
		//将工具栏按钮的基本属性依次添加
		for (i = 0; i < 5; i++)
		{
			tbs[i].iBitmap = ImageID[i];
			tbs[i].iString = (int)marks[i];		//是一个PTR_INT类型数据,用来存放32位地址,是按钮标签索引
			tbs[i].fsStyle = TBSTYLE_BUTTON;	//按钮风格
			tbs[i].fsState = TBSTATE_ENABLED;	//按钮状态
		}
		//将工具指令与相应菜单栏的指令对应
		tbs[0].idCommand = ID__BOOK_INFO;
		tbs[1].idCommand = ID__BOOK_INPUT;
		tbs[2].idCommand = ID__SALE_QUERY;
		tbs[3].idCommand = ID_TB_CONFIG;
		tbs[4].idCommand = ID__TB_EXIT;
		//向工具栏传递增加按钮的信息
		SendMessage(hToolbar, TB_ADDBUTTONS, 5, (LPARAM)(LPTBBUTTON)tbs);
		SendMessage(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(80, 60));	//设置按钮大小
		SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID__OPERATOR_M:		//操作员管理项
			if((x=g_level)>1)		//只有当操作员级别大于1,才能操作
			{
				DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_OPERATOR_M),
					hDlg, Operator_M_Proc);						//创建操作员管理对话框
			}
			else
			{
				MessageBox(hDlg, TEXT("您无权进行此操作"), TEXT("权限等级限制"), MB_ICONERROR);
			}
			break;
		case ID__BOOK_INFO:			//图书信息管理菜单项
			DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_INFO),
				hDlg, Book_Info_Proc);
			break;
		case ID__PROVIDER_INFO:		//供应商信息管理菜单项
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_PROVIDER_INFO),
			hDlg, Provider_Info_Proc);*/
			break;
		case ID__BOOK_KIND:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_KINDS),
			hDlg, Book_Kinds_Proc);*/
			break;
		case ID__CK_INFO:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_STORE_INFO),
			hDlg, Store_Info_Proc);*/
			break;
		case ID__DESK_INFO:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_DESC_INFO),
			hDlg, Desc_Info_Proc);*/
			break;
		case ID__BOOK_INPUT:
			DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_INPUT),
			hDlg, Book_Input_Proc);
			break;
		case ID__INPUT_BACK:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_INPUT),
			hDlg, Book_Input_Back_Proc);*/
			break;
		case ID__BOOK_ADJUST:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_ADJUST),
			hDlg, Book_Adjust_Proc);*/
			break;
		case ID__SALE_M:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_SALE),
			hDlg, Book_Sale_Proc);*/
			break;
		case ID__SALE_BACK:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_BOOK_SALE),
			hDlg, Book_Sale_Back_Proc);*/
			break;
		case ID__INPUT_QUERY:
			DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_QUERY),
			hDlg, Book_Input_Query_Proc);
			break;
		case ID__INPUT_BACK_QUERY:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_QUERY),
			hDlg, Book_Input_Back_Query_Proc);*/
			break;
		case ID__SALE_QUERY:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_QUERY),
			hDlg, Book_Sale_Query_Proc);*/
			break;
		case ID__SALE_BACK_QUERY:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_QUERY),
			hDlg, Book_Sale_Back_Query_Proc);*/
			break;
		case ID__STOCK_QUERY:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_STOCKQUERY),
			hDlg, Book_Stock_Query_Proc);*/
			break;
		case ID_TB_CONFIG:
			/*DialogBox(g_hInstance, MAKEINTRESOURCE(ID_DLG_CONFIG),
			hDlg, ConfigDlgProc);*/
			break;
		case ID__TB_EXIT:
			PostQuitMessage(0);
			break;
		case ID__EXIT:
			PostQuitMessage(0);
			break;
			
		}
		return 0;
		break;
	case WM_PAINT:
		hdc = BeginPaint(hDlg, &ps);
		GetWindowRect(hDlg, &rect);
		Width = rect.right - rect.left;
		Height = rect.bottom - rect.top;
		memDC = CreateCompatibleDC(hdc);			//创建与当前设备环境句柄兼容的设备环境句柄
		bmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));		//获得图片
		GetObject(bmp, sizeof(BITMAP), &mBitmap);
		SelectObject(memDC, bmp);
		StretchBlt(hdc, 0, 0, Width, Height, memDC, 0, 0, mBitmap.bmWidth, mBitmap.bmHeight, SRCCOPY);
		DeleteDC(memDC);

		EndPaint(hDlg, &ps);
		return 0;
	case WM_CLOSE:
		PostQuitMessage(0);
		
	case WM_DESTROY:
		
		break;
		return 0;
	}
	return 0;
}

吐槽一句,误点出来的代码框删不掉啊哭TAT




   


猜你喜欢

转载自blog.csdn.net/yong_ss/article/details/79252353