当前位置:文档之家› Windows界面编程-背景图片、透明特效使用

Windows界面编程-背景图片、透明特效使用

Windows界面编程-背景图片、透明特效使用
Windows界面编程-背景图片、透明特效使用

Windows界面编程第一篇位图背景与位图画刷

可以通过WM_CTLCOLORDLG消息来设置对话框的背景,MSDN 上对这个消息的说明如下:

The WM_CTLCOLORDLG message is sent to a dialog box before the

system draws the dialog box. By responding to this message, the dialog box can set its text and background colors using the specified display device context handle.

当窗口消息响应函数接收这个消息时,wParam表示对话框的设备上下方即HDC,lParam表示对话框的句柄。如果程序处理了这个消息,应返回一个画刷。系统将会用这个画刷来重绘对话框背景。

因此我们在这个WM_CTLCOLORDLG消息中得到对话框的大小,并通过StretchBlt函数将位图缩放后贴到对话框的HDC中就完成了对话框背景的设置,然后返回一个空画刷给系统,这样系统就不会将位图背景给覆盖了。

代码非常简单,要注意的是在使用StretchBlt函数缩放位图时,最好先使用

SetStretchBltMode函数来设置下位图内容伸展模式,这样可以避免缩放后位图失真严重。SetStretchBltMode函数原型如下:

int SetStretchBltMode(

HDC hdc, // handle to DC

int iStretchMode // bitmap stretching mode

);

第一个参数就是设备上下方即HDC。

第二个参数有四种设置:

1. BLACKONWHITE or STRETCH_ANDSCANS

如果两个或多个像素得合并成一个像素,那么StretchBlt会对像素执行一个逻辑AND运算。这样的结果是只有全部的原始像素是白色时该像素才为白色,其实际意义是黑色像素控制了白色像素。这适用于白色背景中主要是黑色的单色点阵图。

2. WHITEONBLACK or STRETCH_ORSCANS

如果两个或多个像素得合并成一个像素,那么StretchBlt会对像素执行逻辑OR运算。这样的结果是只有全部的原始像素都是黑色时该像素才为黑色,也就是说由白色像素决定颜色。这适用于黑色背景中主要是白色的单色点阵图。

3. COLORONCOLOR or STRETCH_DELETESCANS

简单地消除图素行或列,而没有任何逻辑组合。这是通常是处理彩色点阵图的最佳方法。

4. HALFTONE or STRETCH_HALFTONE

根据组合起来的来源颜色来计算目的的平均颜色。

其它技术细节可以见代码中的注释,完整代码如下(也可以下载,下载地址为:https://www.doczj.com/doc/1815587938.html,/download/morewindows/4947377):[cpp]view plaincopyprint?

1.// 对话框位图背景 - WM_CTLCOLORDLG中使用StretchBlt贴图

2.//By MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)

3.#include

4.#include "resource.h"

5.

6.const char szDlgTitle[] = "位图背景使用StretchBlt贴

图 MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)";

7.

8.// 对话框消息处理函数

9.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

;

10.

11.int APIENTRY WinMain(HINSTANCE hInstance,

12.HINSTANCE hPrevInstance,

13.LPSTR lpCmdLine,

14.int nCmdShow)

15.{

16. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);

17.return 0;

18.}

19.

20.

21.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

22.{

23. RECT rcDialog;

24.HBITMAP hBitmap;

25.static BITMAP s_bm;

26.static HDC s_hdcMem;

27.

28.switch (message)

29. {

30.case WM_INITDIALOG:

31.// 设置对话框标题

32. SetWindowText(hDlg, szDlgTitle);

33.// 设置对话框大小可调节

34. SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_S

IZEBOX);

35.

36.// 加载背影图片

37. hBitmap = (HBITMAP)LoadImage(NULL, "005.bmp", IMAGE_BITMAP, 0, 0, LR

_LOADFROMFILE | LR_CREATEDIBSECTION);

38.if (hBitmap == NULL)

39. {

40. MessageBox(hDlg, "LoadImage failed", "Error", MB_ICONERROR);

41. exit(0);

42. }

43.else

44. {

45.// 将背影图片放入HDC - s_hdcMem

46.HDC hdc;

47. hdc = GetDC(hDlg);

48. s_hdcMem = CreateCompatibleDC(hdc);

49. SelectObject(s_hdcMem, hBitmap);

50. ReleaseDC(hDlg, hdc);

51.

52.// 得到位图信息

53. GetObject(hBitmap, sizeof(s_bm), &s_bm);

54. }

55.

56.return 0;

57.

58.case WM_COMMAND:

59.switch (LOWORD(wParam))

60. {

61.case IDCANCEL:

62. DeleteDC(s_hdcMem);

63. EndDialog(hDlg, LOWORD(wParam));

64.return TRUE;

65. }

66.break;

67.

68.

69.case WM_SIZE:

70. InvalidateRect(hDlg, NULL, TRUE);

71.return TRUE;

72.

73.case WM_CTLCOLORDLG:

74. GetClientRect(hDlg, &rcDialog);

75.//通过SetStretchBltMode的设置能使StretchBlt在缩放图像更加清晰

76. SetStretchBltMode((HDC)wParam, COLORONCOLOR);

77. StretchBlt((HDC)wParam, 0, 0, rcDialog.right, rcDialog.bottom, s_hdc

Mem, 0, 0, s_bm.bmWidth, s_bm.bmHeight, SRCCOPY);

78.return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));

79. }

80.return FALSE;

81.}

运行结果如下:

在上面这种方法中,我们是在WM_CTLCOLORDLG中贴图来完成背景设置了,也可以创建一个位图画刷,然后在WM_CTLCOLORDLG消息中直接返回这个画刷,这样系统将完成贴图功能。

位图画刷的创建函数为CreatePatternBrush,其函数原型如下:HBRUSH CreatePatternBrush(

HBITMAP hbmp // handle to bitmap

);

只要给这个函数传入位图句柄即可,完整代码如下(下载地址为:https://www.doczj.com/doc/1815587938.html,/download/morewindows/4947377):

[cpp]view plaincopyprint?

1.// 对话框位图背景 - 直接在WM_CTLCOLORDLG中使用位图画刷

2.//By MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)

3.#include

4.#include "resource.h"

5.

6.const char szDlgTitle[] = "位图画

刷 MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)";

7.

8.

9.// 对话框消息处理函数

10.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

;

11.

12.int APIENTRY WinMain(HINSTANCE hInstance,

13.HINSTANCE hPrevInstance,

14.LPSTR lpCmdLine,

15.int nCmdShow)

16.{

17. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);

18.return 0;

19.}

20.

21.

22.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

23.{

24.static HBRUSH s_hBitmapBrush; //位图画刷

25.

26.switch (message)

27. {

28.case WM_INITDIALOG:

29.// 设置对话框标题

30. SetWindowText(hDlg, szDlgTitle);

31.// 设置对话框大小可调节

32. SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_S

IZEBOX);

33.

34.// 加载背影图片

35.HBITMAP hBitmap;

36. hBitmap = (HBITMAP)LoadImage(NULL, "005.bmp", IMAGE_BITMAP, 0, 0, LR

_LOADFROMFILE | LR_CREATEDIBSECTION);

37.if (hBitmap == NULL)

38. {

39. MessageBox(hDlg, "LoadImage failed", "Error", MB_ICONERROR);

40. exit(0);

41. }

42.

43.// 创建位图画刷

44. s_hBitmapBrush = CreatePatternBrush(hBitmap);

45.return 0;

46.

47.

48.case WM_COMMAND:

49.switch (LOWORD(wParam))

50. {

51.case IDCANCEL:

52. DeleteObject(s_hBitmapBrush);

53. EndDialog(hDlg, LOWORD(wParam));

54.return TRUE;

55. }

56.break;

57.

58.case WM_CTLCOLORDLG:

59.return (BOOL)s_hBitmapBrush;

60. }

61.return FALSE;

62.}

运行结果如下:

注意,这两做法在窗口大小超过位图大小时会表现不同,前一种做法会拉伸位图以适应窗口大小,后一种做法是直接平铺。详见下图:

本篇《Windows界面编程第一篇位图背景与位图画刷》主要介绍了通过WM_CTLCOLORDLG消息来设置对话框的背景,在Windows系统中还有类似于WM_CTLCOLORDLG消息的还有WM_CTLCOLORBTN,WM_CTLCOLOREDIT,WM_CTLCOLORLISTBOX,

WM_CTLCOLORSCROLLBAR,WM_CTLCOLORSTATIC这五种来分

别管理按钮,编辑框,列表框,滚动条,静态框。有兴趣的读者可以试验下。

下一篇将介绍调节窗体透明度的方法,欢迎继续浏览《Windows界面编程第二篇半透明窗体》

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

Windows界面编程第二篇半透明窗体

上一篇《Windows界面编程第一篇位图背景与位图画刷》介绍了通过WM_CTLCOLORDLG消息来来设置对话框的背景以及位图画刷的使用。本篇将介绍动态调节窗体透明度的方法。

调节窗体透明度可以先使用SetWindowLong为窗体加上

WS_EX_LAYERED属性,再使用来SetLayeredWindowAttributes指定窗体的透明度。这样就可以在程序运行时动态的调节窗体的透明度了。

下面先介绍下SetWindowLong和SetLayeredWindowAttributes函数。SetWindowLong可以用来设置窗口的一些属性,其函数原型如下:

LONG SetWindowLong(

HWND hWnd,

int nIndex,

LONG dwNewLong

);

第一个参数表示窗口句柄。

第二个参数代表要设置的哪一种值,如GWL_STYLE表示将设置窗口的风格,这个参数还可以取GWL_EXSTYLE,GWL_WNDPROC,DWL_DLGPROC,GWL_HINSTANCE,GWL_USERDATA等等。

第三个参数表示要设置的值。

比如要设置对话框也能够可调节窗口大小,可以用:

// 设置对话框大小可调节

SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STY LE) | WS_SIZEBOX);

SetLayeredWindowAttributes在MSDN上解释如下:

The SetLayeredWindowAttributes function sets the opacity and transparency color key of a layered window.

其函数原型为:

BOOL SetLayeredWindowAttributes(

HWND hwnd,

COLORREF crKey,

BYTE bAlpha,

DWORD dwFlags

);

第一个参数表示窗口句柄。

第二个参数表示透明色。

第三个参数表示透明度。

第四个参数表示函数将完成什么样的功能,设置成LWA_COLORKEY 表示为窗口指定了透明色,设置成LWA_ALPHA表示将调整窗口的透明度,可以同时设置这两种功能。

程序代码还将用到Slider控件,这种控件可以有如下操作:

1.通过SendMessage + TBM_SETRANGE来设置滑块变化的范围。2.通过SendMessage + TBM_SETPOS来设置滑块当前位置。

3.通过SendMessage + TBM_GETPOS来获得滑块当前位置。

4.当滑块位置发生变化时,在其父窗口中通过WM_HSCROLL或WM_VSCROLL来响应消息。

下面给出完整的源代码(下载地址:

https://www.doczj.com/doc/1815587938.html,/download/morewindows/4947386)

[cpp]view plaincopyprint?

1.// 可变透明度窗体先加上WS_EX_LAYERED属性再

SetLayeredWindowAttributes设置透明度

2.//By MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)

3.#include

4.#include

5.#include "resource.h"

6.const char szDlgTitle[] = "可变透明度窗

体 MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)";

7.// 对话框消息处理函数

8.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPAR

AM wParam, LPARAM lParam);

9.

10.int APIENTRY WinMain(HINSTANCE hInstance,

11.HINSTANCE hPrevInstance,

12.LPSTR lpCmdLine,

13.int nCmdShow)

14.{

15. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALO

G1), NULL, DlgProc);

16.return 0;

17.}

18.

19.

20.BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPA

RAM wParam, LPARAM lParam)

21.{

22.const int INIT_TRANSPARENT = 200; //窗体初始透

明度

23.static HBRUSH s_hBitmapBrush; //位图画刷

24.

25.switch (message)

26. {

27.case WM_INITDIALOG:

28.// 设置对话框标题

29. SetWindowText(hDlg, szDlgTitle);

30.

31.// 加载背影图片

32.HBITMAP hBitmap;

33. hBitmap = (HBITMAP)LoadImage(NULL, "005.bm

p", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATE DIBSECTION);

34.if (hBitmap == NULL)

35. {

36. MessageBox(hDlg, "LoadImage failed", "

Error", MB_ICONERROR);

37. exit(0);

38. }

39.

40.// 创建位图画刷

41. s_hBitmapBrush = CreatePatternBrush(hBitma

p);

42.

43.// 设置分层属性

44. SetWindowLong(hDlg, GWL_EXSTYLE, GetWindow

Long(hDlg, GWL_EXSTYLE) | WS_EX_LAYERED);

45.// 设置透明

度 0 - completely transparent 255 - opaque

46. SetLayeredWindowAttributes(hDlg, 0, INIT_T

RANSPARENT, LWA_ALPHA);

47.

48.// 设置滑动条变化范围

49. SendMessage(GetDlgItem(hDlg, IDC_SLIDER_TR

ANSPARENT), TBM_SETRANGE, (WPARAM)FALSE, MAKELONG(0 , 255));

50.// 设置滑块初始位置

51. SendMessage(GetDlgItem(hDlg, IDC_SLIDER_TR

ANSPARENT), TBM_SETPOS, (WPARAM)TRUE, INIT_TRANSPAR ENT);

52.return 0;

53.

54.

55.case WM_COMMAND:

56.switch (LOWORD(wParam))

57. {

58.case IDCANCEL:

59. DeleteObject(s_hBitmapBrush);

60. EndDialog(hDlg, LOWORD(wParam));

61.return TRUE;

62. }

63.break;

64.

65.

66.case WM_HSCROLL: // slider control 滑块位置有变

化时的响应函数

67. {

68.// 获取当前滑块位置

69.int nTransparent = SendMessage(GetDlgI

tem(hDlg, IDC_SLIDER_TRANSPARENT), TBM_GETPOS, 0, 0 );

70.// 设置新透明度

71. SetLayeredWindowAttributes(hDlg, 0, nT

ransparent, LWA_ALPHA);

72. }

73.break;

74.

75.

76.case WM_CTLCOLORDLG: //对话框背影

77.return (BOOL)s_hBitmapBrush;

78. }

79.return FALSE;

80.}

运行结果如下:

在本篇文章中我们通过SetWindowLong为窗体加上WS_EX_LAYERED 属性,再使用SetLayeredWindowAttributes完成窗体的透明度调节。下面两篇也将使用这两个函数来完成另一个功能——异形窗口(异形窗体)。异形窗口可以使得窗口更加美观,它能灵活的变动窗口的形状。欢迎继续浏览《Windows界面编程第三篇异形窗体普通版》和《Windows界面编程第四篇异形窗体高富帅版》

Windows界面编程第三篇异形窗体普通版上一篇《Windows界面编程第二篇半透明窗体》介绍了先使用SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用

SetLayeredWindowAttributes调整窗体的透明度。本篇将使用这二个函数来完成另一个实用的功能——异形窗口(异形窗体)。

异形窗口的原理很简单,首先加载一张位图画刷作窗口背景,然后设置透明色就可以使得窗口由矩形变成任意形状。这样使得窗口的显示更加美观。

下面先简单介绍下Win32 SDK方式创建窗口的流程(按《Windows 程序设计》中的大体流程):

1.设置WNDCLASS类型的变量,这个变量将描述窗口的风格、窗口消息处理函数、程序图标、光标、窗口背景画刷等待。

2.使用RegisterClass将WNDCLASS类型的变量注册下。

3.使用CreateWindow或CreateWindowEx创建窗口,这里可以设置窗口的初始位置、初始大小、扩展属性等等。

4.通过ShowWindow和UpdateWindow将窗口显示出来。

5.窗口显示完成后,在WinMain()函数中添加消息处理:MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

通过这五步就完成了一个窗口的创建了。

对于窗口消息函数,一般只要在WM_DESTROY消息中调用下PostQuitMessage(0);其它的消息都可以使用默认消息处理函数DefWindowProc。

对于异形窗口,可以在WM_CREATE即窗口初始化时设置好透明色就完成了窗口形状的改变,不过为了支持鼠标对窗口的拖曳,还要在WM_LBUTTONDOWN消息中加入:

PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);

这样,异形窗口就可以在屏幕上像普通窗口一样的移动了。

完整的源代码如下所示(下载地址:

https://www.doczj.com/doc/1815587938.html,/download/morewindows/4966815):

[cpp]view plaincopyprint?

1.// 异形窗口1 窗口背景使用位图画刷再指定透明色

2.//By MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)

3.#include

4.

5.const char szAppName[] = "异形窗口

1 MoreWindows-(https://www.doczj.com/doc/1815587938.html,/MoreWindows)";

6.

7./*

8. * 函数名称: GetWindowSize

9. * 函数功能: 得到窗口的宽高

10. * hwnd 窗口句柄

11. * pnWidth 窗口宽

12. * pnHeight 窗口高

13.*/

14.void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);

15.

16.

17./*

18. * 函数名称: InitBitmapWindow

19. * 函数功能: 位图窗口初始化

20. * hinstance 进程实例

21. * hBitmap 位图句柄

22. * nCmdshow 显示方式-与ShowWindow函数的第二个参数相同

23.*/

24.BOOL InitBitmapWindow(HINSTANCE hinstance, HBITMAP hBitmap, int nCmdshow);

25.

26.// 位图窗口消息处理函数

27.LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam,

LPARAM lParm);

28.

29.

30.int APIENTRY WinMain(HINSTANCE hInstance,

31.HINSTANCE hPrevInstance,

32.LPSTR lpCmdLine,

33.int nCmdShow)

34.{

35.//设置窗口背景画刷为图片画刷,再指定透明颜色即可以创建透明区域。

36.HBITMAP hBitmap;

37. hBitmap = (HBITMAP)LoadImage(NULL, "Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_L

OADFROMFILE);

38.if (hBitmap == NULL)

39. {

40. MessageBox(NULL, "位图加载失败", "Error", MB_ICONERROR);

41.return 0;

42. }

43.if (!InitBitmapWindow(hInstance, hBitmap, nCmdShow))

44.return 0;

45.

相关主题
文本预览
相关文档 最新文档