微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Windows界面编程第四篇 异形窗体 高富帅版

    上一篇Windows界面编程第三篇 异形窗体 普通版》介绍了异形窗口(异形窗体)的创建,其主要步骤为——先通过创建位图画刷来做窗口的背景画刷,再通过SetwindowLong为窗体加上WS_EX_layered属性,然后使用SetlayeredWindowAttributes指定窗口的透明色来完成窗口形状的调整。并且为了使异形窗口支持鼠标的拖曳,在WM_LBUTTONDOWN消息中作了特殊处理。

然后在下图中有非常相似的两个异形窗体,只不过,左边的异形窗体小,右边的异形窗体大。这个可以怎么实现了?

 

分享图片

先通过其它软件来缩放位图,然后再让程序加载这种方式来指定异形窗口的大小。这种方法虽然可以完成任务,但毕竟太OUT了。

由《Windows界面编程第一篇位图背景与位图画刷》可以想到不用位图画刷,而直接在窗口背景绘制时使用StretchBlt来缩放位图至窗口大小,这样就可以达到指定窗口大小的功能

由于异形窗口运行后无法通过鼠标来动态调整窗口大小,因此可以窗口初始化时就可以先缩放位图并加载到一个缓冲HDC中,然后再在窗口背景绘制时使用BitBlt来贴图。这种做法只需要缩放位图一次,在每次背景绘制时只须拷贝位图,对程序的效率会有提高。下面给出完整源代码(下载地址:http://download.csdn.net/download/morewindows/4966819

// 异形窗口2 在WM_ERASEBKGND消息中自贴图
//By MoreWindows-(http://blog.csdn.net/MoreWindows)
#include <windows.h>
const char szAppName[] = "异形窗口2 MoreWindows-(http://blog.csdn.net/MoreWindows)";

/* * 函数名称: GetwindowSize * 函数功能: 得到窗口的宽高 * hwnd 窗口句柄 * pnWidth 窗口宽 * pnHeight 窗口高 */
void GetwindowSize(HWND hwnd,int *pnWidth,int *pnHeight);


/* * 函数名称: InitBitmapWindow * 函数功能: 位图窗口初始化 * hinstance 进程实例 * nWidth 窗口宽 * nHeight 窗口高 * nCmdshow 显示方式-与ShowWindow函数的第二个参数相同 */
BOOL InitBitmapWindow(HINSTANCE hinstance,int nWidth,int nHeight,int nCmdshow);

// 位图窗口消息处理函数
LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd,UINT message,WParaM wParam,LParaM lParm);

          
HBITMAP  g_hBitmap;
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdshow) {
    //先创建一个无背影画刷窗口,
	//然后在WM_CREATE中并指定透明颜色,缩放位图后加载至s_hdcmem中.
	//最后在WM_ERASEBKGND中用s_hdcmem贴图即可
	g_hBitmap = (HBITMAP)LoadImage(NULL,"Kitty.bmp",IMAGE_BITMAP,0,LR_LOADFROMFILE);
	if (g_hBitmap == NULL)
	{
		MessageBox(NULL,"位图加载失败","Error",MB_ICONERROR);
		return 0;
	}

	// 设置异形窗口大小
	BITMAP bm;
	Getobject(g_hBitmap,sizeof(bm),&bm);
	int nWindowWidth = bm.bmWidth;
	int nWindowHeight = bm.bmHeight + 100; //拉高100高度

	if (!InitBitmapWindow(hInstance,nWindowWidth,nWindowHeight,nCmdshow))
		return 0;

	MSG msg;
	while (GetMessage(&msg,NULL,0))
	{
		TranslateMessage(&msg);
		dispatchMessage(&msg);
	}
	DeleteObject(g_hBitmap);

	return msg.wParam;
}


BOOL InitBitmapWindow(HINSTANCE hinstance,int nCmdshow) {
	HWND hwnd;
	WNDCLASS wndclass;
	
	wndclass.style       = CS_VREDRAW | CS_HREDRAW;
	wndclass.lpfnWndProc = BitmapWindowWndPrco;	
	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(NULL_Brush);//窗口背影画刷为空
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = szAppName;
	
	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL,"Program Need Windows NT!",MB_ICONERROR);
		return FALSE;
	}
	
	hwnd = CreateWindowEx(WS_EX_TOPMOST,szAppName,WS_POPUP,CW_USEDEFAULT,nWidth,nHeight,hinstance,NULL);
	if (hwnd == NULL)
		return FALSE;
	
	ShowWindow(hwnd,nCmdshow);
	UpdateWindow(hwnd);
	
	return TRUE;
}

LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd,LParaM lParm) {
	static HDC s_hdcmem; //放置缩放后的位图
	
	switch (message)
	{
	case WM_CREATE:
		{
			// 设置分层属性
 			SetwindowLong(hwnd,GWL_EXSTYLE,getwindowlong(hwnd,GWL_EXSTYLE) | WS_EX_layered);
			// 设置透明色
			COLORREF clTransparent = RGB(0,0);
 			SetlayeredWindowAttributes(hwnd,clTransparent,LWA_COLORKEY);
			
			// 缩放位图
			// 加载位图到hdcTemp中
			HDC hdc = GetDC(hwnd);
			HDC hdcTemp = CreateCompatibleDC(hdc);
			SelectObject(hdcTemp,g_hBitmap);

			// 得到窗口大小
			int nWidth,nHeight;
			GetwindowSize(hwnd,&nWidth,&nHeight);

			// 创建与窗口大小相等且能容纳位图的HDC - s_hdcmem
			s_hdcmem = CreateCompatibleDC(hdc);
			HBITMAP hbmp = CreateCompatibleBitmap(hdc,nHeight);
			SelectObject(s_hdcmem,hbmp);

			// 将原位图缩放到窗口大小
			BITMAP bm;
			Getobject(g_hBitmap,&bm);
			StretchBlt(s_hdcmem,hdcTemp,bm.bmWidth,bm.bmHeight,SRCcopY);
			
			// 释放资源
			DeleteDC(hdcTemp);
			ReleaseDC(hwnd,hdc);
		}
		return 0;

		
	case WM_KEYDOWN: 
		switch (wParam)
		{
		case VK_ESCAPE: //按下Esc键时退出
			SendMessage(hwnd,WM_DESTROY,0);
			return TRUE;
		}
		break;
	

	case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口
		PostMessage(hwnd,WM_SYSCOMMAND,SC_MOVE | HTCAPTION,0); 
		return TRUE;
				
	case WM_ERASEBKGND: //在窗口背景中直接贴图
		{
			HDC hdc = (HDC)wParam;
			int nWidth,&nHeight);
			BitBlt(hdc,s_hdcmem,SRCcopY);
			return TRUE;
		}

	case WM_DESTROY:
		DeleteDC(s_hdcmem);
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParm);
}


void GetwindowSize(HWND hwnd,int *pnHeight) {
	RECT rc;
	GetwindowRect(hwnd,&rc);
	*pnWidth = rc.right - rc.left;
	*pnHeight = rc.bottom - rc.top;
}

运行程序将得到如文章中每一张图右边所示的异形窗口。

 

最后总结一下异形窗口的“三要素”:

1.WS_EX_layered属性

2.以位图为窗口背景(自贴图或位图画刷)

3.指定透明色

 

本文配套程序下载地址为:http://download.csdn.net/download/morewindows/4966819

 

当窗口的背景用彩色图片来装饰时,其它控件如果还是用灰色的背景会显的比较不谐调,《Windows界面编程第五篇 静态控件背景透明化》将介绍如何为静态框设置透明背景。

 

转载请标明出处,原文地址:http://www.voidcn.com/article/p-rvmjumxh-yt.html

欢迎关注微博:http://weibo.com/MoreWindows

 


 

 

分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://www.cnblogs.com/captainbed

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐