当前位置:C++技术网 > 精选软件 > Win32实现在窗口贴图,Win32设置窗口背景

Win32实现在窗口贴图,Win32设置窗口背景

更新时间:2015-12-16 19:40:36浏览次数:1+次

    使用MFC我们设置窗口背景的方法其实和Win32差不多,不过,虽然你会MFC设置窗口背景,然而切换到Win32环境,不一定会哦。然而你会Win32环境下的实现,MFC也是分分钟的事情。实现的效果图如下:
    Win32实现在窗口贴图,Win32设置窗口背景
    在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,就是相当于要画图的位置就是图片数据上,而不是在窗口上绘图。

    然而我们这里只是将图片提取出来就可以了。不过我在将图片贴图到窗口前,在图片上输出了一串文字。然而你可以看到文字并没有完整的输出来,因为图片比较小,字是输出在图片上的。最后将图片数据一次性贴在窗口上。

    所以看到的文字不完整,而且图片还是一部分,没有拉伸,直接是原始粘贴。效果如下:

    Win32实现在窗口贴图,Win32设置窗口背景

    选择图片的代码如下:

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;
}