在MFC中你可以直接调用一个窗口类的函数就可以设置窗口背景颜色了,然而在Win32中,可没有这些函数给你使用哦。而是要用GDI函数来实现,而这些实现就需要你具备一点基础知识哦。
我们要实现窗口贴图,首先要准备一个Bmp图片。你在VS环境下的“资源视图”中添加资源,导入一张bmp图片,然后就可以在“资源视图”下的【Bitmap】看到一个ID为IDB_BITMAP1的图片资源。这个就是我们将要使用的图片,贴图到窗口的整个客户区。
东西准备好后,我们就准备写代码贴图了哦。我们在WM_PAINT消息下处理。消息最开始就将图片贴满整个客户区,而且窗口大小改变后,我们在WM_SIZE消息下获取窗口的大小,然后在WM_PAINT下又会重绘。所以,不管窗口怎么调整,这个图片始终都是在最底层显示的,就是所谓的窗口背景图片咯。
为了方便存储客户区的大小,我就用了POINT结构体来存储。虽然POINT本来是用来存储坐标的,然而我们借用一下,感觉挺好。用POINT的x成员存储客户区的宽度,用y存储客户区的高度。这样就不用定义两个变量,或者定义一个这样的结构体。不过,在标准的开发中,不建议这样使用,因为别人看你代码的时候,可能误解为坐标点而始终都陷入其中,会骂你的,哈哈哈。这里告诉你一个信号,就是不要思维定势了,只要特征符合,使用起来也很不错,你实在是懒的话,可以将变量名取得明显点,这样也好识别变量的意义。
在WM_SIZE消息中,LPARAM参数存储的是当前客户区的大小,是一个DWORD双字数据类型,低字部分保存了客户区宽度,高字部分存储了客户区高度。取高字和低字,请使用宏HIWORD和LOWORD。这些宏的详细解释,请参考《DWORD、WORD的高低部分提取和合成宏代码示例》。
所以,只要窗口大小改变,就可以更新客户区的大小,代码如下:
case WM_SIZE:
pt.x = LOWORD(lParam);//存储客户区宽度
pt.y = HIWORD(lParam);//存储客户区高度
return 0;
这是两个基本的准备。图片准备好了,客户区大小也知道了。下面就是准备开始画图了。我们先要加载位图,使用函数LoadBitmap,而因为我们的图片是自己添加的,不是系统预设的,所以要用应用实例句柄,我们在WinMain函数就将应用实例句柄存储起来,存放在全局变量g_hInstance中。LoadBitmap的第二个参数是一个字符串,而我们自动添加的位图默认是一个整数ID,所以要用MAKEINTRESOURCE宏将整数ID转换成字符串形式传入。函数返回一个位图句柄。代码如下:hBitmap = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
因为我们的图片要贴图,虽然有了位图的句柄,该如何使用呢?这是很多人都不清楚的,也很郁闷。我们一般得到的句柄是窗口这样的句柄,和图片没有半毛钱关系,那么如何将位图和DC关联起来呢?那就是内存DC了。我们调用LoadBitmap函数将图片加载到内存后,我们就可以创建一个内存DC,并将位图选进内存DC中,那么就可以操作位图了。将图片选入内存DC,就是相当于要画图的位置就是图片数据上,而不是在窗口上绘图。然而我们这里只是将图片提取出来就可以了。不过我在将图片贴图到窗口前,在图片上输出了一串文字。然而你可以看到文字并没有完整的输出来,因为图片比较小,字是输出在图片上的。最后将图片数据一次性贴在窗口上。
所以看到的文字不完整,而且图片还是一部分,没有拉伸,直接是原始粘贴。效果如下:
选择图片的代码如下:
hBitmap = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
hMem = CreateCompatibleDC(hdc);
SelectObject(hMem,hBitmap);
TextOut(hMem,0,100,Info,lstrlen(Info));
最后一步就是贴图了。贴出使用BitBlt函数即可。这个函数前面设置的是要在窗口那个区域绘画,所以第2-5的四个参数依次为窗口显示图片的起点xy和显示区域大小。我们这里将宽度和高度设置为了整个客户区的大小。不过因为图片本身太小,只有左上角一部分有图片。然而紧接着的三个参数依次为图片所在的内存DC,从那开始复制图片,没有指定图片的大小,也就是要复制起点坐标以外的所有图片内容。最后是复制的方式,我们使用SRCCOPY就是表示直接复制图片的像素粘贴在窗口客户区中即可。以下是完整的代码:
#include "windows.h"
#include "resource.h"
#include <tchar.h>
// - 项目是Unicode字符集
HINSTANCE g_hInstance=NULL;
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc,hMem;
PAINTSTRUCT ps;
TCHAR Info[100]=_T("美女哦 - 【C++技术网http://www.cjjjs.com】");
HBITMAP hBitmap;
static POINT pt;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
hBitmap = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
hMem = CreateCompatibleDC(hdc);
SelectObject(hMem,hBitmap);
TextOut(hMem,0,100,Info,lstrlen(Info));
BitBlt(hdc,0,0,pt.x,pt.y,hMem,0,0,SRCCOPY);
EndPaint(hwnd,&ps);
return 0;
case WM_SIZE:
pt.x = LOWORD(lParam);//存储客户区宽度
pt.y = HIWORD(lParam);//存储客户区高度
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
if(!RegisterClass(&wndClass))
{
return 0;
}
g_hInstance = hInstance;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,500,500,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}