我打算写一个MDI程序北京设置的类,今后自己使用着方便,实现过程中发现程序刚开始运行时图片能正常显示,但刷新后(不论是因为缩放窗口还是因为重新获得焦点)仿佛程序便不起作用了,哪位达人了解这种情况,切盼帮助一下。
#pragma once
///////////////////////////////////////
//设置MDI程序背景的类
///////////////////////////////////////
class CMdiBackground
{
private:
CMDIFrameWnd *m_pMainFrame;public:
static HBITMAP hBmp;//图片句柄
static WNDPROC pfnOldWndProc;//旧函数指针
static int BMPH,BMPW;
CMdiBackground(void);
CMdiBackground(CMDIFrameWnd *pMainFrame);
void SetMainFrame(CMDIFrameWnd *pMainFrame){m_pMainFrame=pMainFrame;};
static LRESULT CALLBACK fnNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam);
public:
~CMdiBackground(void);
void SetBkFunc(void);
};
===========================================
#include "StdAfx.h"
#include "ElecGridMap.h"
#include "MdiBackground.h"
HBITMAP CMdiBackground::hBmp;//图片句柄
int CMdiBackground::BMPH,CMdiBackground::BMPW;//图片宽度和高度
WNDPROC CMdiBackground::pfnOldWndProc;//旧函数指针
CMdiBackground::CMdiBackground(void)
{
m_pMainFrame=NULL;
}
CMdiBackground::CMdiBackground(CMDIFrameWnd *pMainFrame)
{
m_pMainFrame=pMainFrame;
SetBkFunc();
}
void CMdiBackground::SetBkFunc(void)
{
if(!m_pMainFrame){MessageBox(NULL, L"错误", L"程序错误,应先设置主窗口指针 !!!", MB_OK);return;}
hBmp = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_MAINPIC));
if (hBmp == NULL){
MessageBox(NULL, L"错误", L"程序背景图不能调入 !!!", MB_OK);
return;
}
CBitmap   bm;  
BITMAP   bwh;   bm.Attach(hBmp);  
bm.GetObject(sizeof(BITMAP),   &bwh);  
bm.Detach();   
BMPW=bwh.bmWidth;
BMPH=bwh.bmHeight;
HWND hMain = m_pMainFrame->GetWindow(GW_CHILD)->GetSafeHwnd();
pfnOldWndProc = (WNDPROC)GetWindowLong(hMain, GWL_WNDPROC);
SetWindowLong(hMain, GWL_WNDPROC, (LONG)fnNewWndProc);
}CMdiBackground::~CMdiBackground(void)
{
}
LRESULT CALLBACK CMdiBackground::fnNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam){
HDC hdc = (HDC)wParam;
HDC hcompdc;
RECT rect;
switch (uMsg) {
case WM_SIZE :
SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)GetDC(hwnd), 0);
return 1;
case WM_ERASEBKGND :
hcompdc = CreateCompatibleDC(hdc);
SelectObject(hcompdc, hBmp);
GetClientRect(hwnd, &rect); if (0 == StretchBlt(hdc, rect.left, rect.top, rect.right, rect.bottom,
hcompdc, 0, 0, BMPW-1, BMPH-1, SRCCOPY))
MessageBox(hwnd, L"错误", L"拉伸绘制图形错误", MB_OK);

return 1;
default :
return CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
}
}

解决方案 »

  1.   

    还要响应WM_PAINT消息,什么都不做,否则默认就覆盖你绘制的背景了
      

  2.   

    WM_ERASEBKGND,当有背景删除消息发生时就会调用,这段程序中每次ERASEBKGND发生的时候都被调用到的,好像是hdc无效,和wm_paint仿佛没有关系。
      

  3.   

    case WM_SIZE : 
    SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)GetDC(hwnd), 0); 
    return 1; -------------
    你GetDC之后在哪Release了?没释放后续的GetDC,绘制操作都会失败,且wm_size是会频繁触发的,严重资源泄漏。
      

  4.   

    没有删除内存DC,这样改一下:
    case WM_ERASEBKGND:
    hcompdc = CreateCompatibleDC(hdc);
    HGDIOBJ oldObj = SelectObject(hcompdc, hBmp);
    GetClientRect(hwnd, &rect);
    if (0 == StretchBlt(hdc, rect.left, rect.top, rect.right, rect.bottom, hcompdc, 0, 0, BMPW-1, BMPH-1, SRCCOPY))
    MessageBox(hwnd, L"错误", L"拉伸绘制图形错误", MB_OK); 
    SelectObject(hcompdc, oldObj);
    DeleteDC(hcompdc);

    return 1;
      

  5.   

    另外,把WM_SIZE消息的响应代码去掉。
      

  6.   

    原来我有段程序是这样写的,就因为下面这个错误才改成现在这个样子,这样写编译不过去
    f:\vc\elecgridmap\elecgridmap\mdibackground.cpp(59) : error C2361: “default”标签跳过“oldObj”的初始化操作
            f:\vc\elecgridmap\elecgridmap\mdibackground.cpp(50) : 参见“oldObj”的声明
      

  7.   

    WM_SIZE去掉不行啊,缩放的时候图像不跟着变了
      

  8.   

    如果不去掉,还需要加上ReleaseDC。
      

  9.   

    改动后能运行的版本,看看还有什么问题,有的话可以另开贴给分
    LRESULT CALLBACK CMdiBackground::fnNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam){
    HDC hdc = (HDC)wParam;
    HDC hcompdc;
    RECT rect;
    HGDIOBJ oldObj;
    HDC tempDC;
    switch (uMsg) {
    case WM_SIZE :
    tempDC=GetDC(hwnd);
    SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)tempDC, 0);
    ReleaseDC(hwnd,tempDC);
    return 1;
    case WM_ERASEBKGND :
    hcompdc = CreateCompatibleDC(hdc);
    oldObj = SelectObject(hcompdc, hBmp);
    GetClientRect(hwnd, &rect); if (0 == StretchBlt(hdc, rect.left, rect.top, rect.right, rect.bottom,
    hcompdc, 0, 0, BMPW-1, BMPH-1, SRCCOPY))
    MessageBox(hwnd, L"错误", L"拉伸绘制图形错误", MB_OK);
    SelectObject(hcompdc, oldObj); 
    DeleteDC(hcompdc); 
    return 1;
    default :
    return CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam);
    }
    }