我写了一个sdk程序,往窗口增加了一个listbox 控件
现在我想给listbox图片背景设置自己的图片
代码如下:void   DrawListBoxBkBitmap(HWND   hwndDlg,   HDC   &hDC) 

HDC  hdcs;
hdcs = ::CreateCompatibleDC(hDC);
HBITMAP m_hBitmap;
BITMAP bm;
m_hBitmap=(HBITMAP)::LoadImage(NULL,"3.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);
GetObject(m_hBitmap, sizeof (BITMAP), &bm); SelectObject(hdcs, m_hBitmap); RECT   rc; 
::GetWindowRect(hwndDlg,   &rc);
::SetStretchBltMode(hDC,COLORONCOLOR);       
::StretchBlt(hDC, 0, 0, rc.right, rc.bottom, hdcs, 0, 0, bm.bmWidth, bm.bmHeight,+SRCCOPY);
}BOOL   CALLBACK   ListBoxProc(HWND   hwndDlg,   UINT   msg,   WPARAM   wParam,   LPARAM   lParam) 

LRESULT   lResult   =   FALSE; 
switch(msg) 

case   WM_ERASEBKGND: 

HDC   hDC   =   (HDC)(wParam); 
DrawListBoxBkBitmap(hwndDlg,   hDC); 

return   TRUE; 

return   CallWindowProc(g_OldListBoxProc,   hwndDlg,   msg,   wParam,   lParam); 
} //main的回调
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
....
case WM_CREATE:
{
GetWindowRect (hWnd, &rect);
hEdit = CreateWindow (TEXT("LISTBOX"), //控件"类名称"
TEXT("Friend"),
WS_CHILD | WS_VISIBLE |LBS_NOTIFY ,
0,
0,
0,
0,
hWnd,
(HMENU)1000, //控件ID
((LPCREATESTRUCT) lParam)->hInstance, //实例句柄
NULL);
  
g_OldListBoxProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, (long)ListBoxProc);现在问题,我启动程序发现背景并没有设置,但是我后来往listbox 增加了一项之后就把背景加载上去了。
请问我想以启动程序就有背景,怎么实现?

解决方案 »

  1.   

    尝试在创建listbox后SendMessage(hlistbox,WM_ERASEBKGND,wParam,lParam)来触发listbox背景的绘制
      

  2.   

    为什么不直接加到WM_PAINT里面呢?
    要是实在不行,你起来就调用一下擦除背景的消息
      

  3.   

    试试创建之后InvalidateRect(hListBox,NULL,TRUE);让其刷新一下。顺便说一下,
    HDC  hdcs;
        hdcs = ::CreateCompatibleDC(hDC);
        HBITMAP m_hBitmap;
        BITMAP bm;
        m_hBitmap=(HBITMAP)::LoadImage(...)hdcs没释放,m_hBitmap每次绘制都加载,也没释放,资源严重泄漏。
      

  4.   

    还有,
    RECT   rc; 
    ::GetWindowRect(hwndDlg,   &rc);
    ::StretchBlt(hDC, 0, 0, rc.right, rc.bottom, hdcs, 0, 0, bm.bmWidth, bm.bmHeight,+SRCCOPY);GetWindowRect之后应该ScreenToClient转换一下,你用StretchBlt,背景会依你程序位置作不同比例拉伸的。
      

  5.   

    case WM_CREATE:
    {
    GetWindowRect (hWnd, &rect);
    // /*
    hEdit = CreateWindow (TEXT("LISTBOX"), //控件"类名称"
    TEXT("Friend"),
    WS_CHILD | WS_VISIBLE |LBS_NOTIFY ,
    0,
    0,
    0,
    0,
    hWnd,
    (HMENU)1000, //控件ID
    ((LPCREATESTRUCT) lParam)->hInstance, //实例句柄
    NULL);
    break;
    }
    case WM_PAINT:
    {
    // g_OldListBoxProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, (long)ListBoxProc);
    HDC  hdcs,hDC;
    hDC = GetDC (hEdit);
    hdcs = ::CreateCompatibleDC(hDC);
    HBITMAP m_hBitmap;
    BITMAP bm;
    m_hBitmap=(HBITMAP)::LoadImage(NULL,"E:\\XMPP\\dms_im_server\\release\\3.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);
    GetObject(m_hBitmap, sizeof (BITMAP), &bm); SelectObject(hdcs, m_hBitmap); RECT   rc; 
    ::GetWindowRect(hEdit,   &rc);
    ::SetStretchBltMode(hDC,COLORONCOLOR);       
    ::StretchBlt(hDC, 0, 0, rc.right, rc.bottom, hdcs, 0, 0, bm.bmWidth, bm.bmHeight,+SRCCOPY);
    ::DeleteObject(hdcs);
    InvalidateRect(hEdit, NULL, TRUE);
    break;
    }
    奇怪。运行的时候有时有背景,有时又没有背景
      

  6.   


    case WM_CREATE:
    {
    GetWindowRect (hWnd, &rect);
    // /*
    hEdit = CreateWindow (TEXT("LISTBOX"), //控件"类名称"
    TEXT("Friend"),
    WS_CHILD | WS_VISIBLE |LBS_NOTIFY ,
    0,
    0,
    0,
    0,
    hWnd,
    (HMENU)1000, //控件ID
    ((LPCREATESTRUCT) lParam)->hInstance, //实例句柄
    NULL); g_OldListBoxProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, (long)ListBoxProc);
    InvalidateRect(hEdit, NULL, TRUE);
    break;
    }
    。。是这样吗?还是没有加载啊
      

  7.   

    在WM_PAINT:你要做的就下面就可以了。
    ::StretchBlt(hDC, 0, 0, rc.right, rc.bottom, hdcs, 0, 0, bm.bmWidth, bm.bmHeight,+SRCCOPY);
    而在CREATE下面你做的就是 把设备DC建立 BMP读入 都一次完成,不要在WM_PAINT下反复加栽了。用到的变量可以做成全局变量。
             
      

  8.   

    我觉得不应该在wm——paint下面吧,现在我点击菜单项背景就没了
    应该是在listbox的消息里刷新吧,而不是主窗体
      

  9.   

    需要响应WM_PAINT的消息是listbox的不是主窗体的
      

  10.   

    试了一下,发现不管是WM_ERASEBKGND和WM_PAINT都没有效。
    不过下述方法是有效的:
    定义一个HBRUSH m_brush变量。
    子类化LISTBOX,加载m_hBitmap后,m_brush = CreatePatternBrush(m_hBitmap);
    然后父窗口响应WM_CTLCOLORLISTBOX消息,直接返回m_brush。
    但是图象是平铺效果,想要拉伸,可以根据其大小CreateCompatibleBitmap创建一个内存图象,拉伸绘制至该图象,利用该图象创建画刷。顺便说一句,创建m_brush后图象句柄就可以释放,m_brush要退出时释放。
      

  11.   

    上面这个方法不需要子类化LISTBOX
      

  12.   

    ls 兄弟能再详细点吗?
    然后父窗口响应WM_CTLCOLORLISTBOX消息,直接返回m_brush。 这句话什么意思?LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {

    HBITMAP   hBitmap  = (HBITMAP)::LoadImage(NULL,"E:\\XMPP\\dms_im_server\\release\\3.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE); 
    HBRUSH m_brush; switch (message)
    {
    case WM_CTLCOLORLISTBOX:
    {
    m_brush = CreatePatternBrush(hBitmap);
                            //然后再怎么办? m_brush 这个何时用到?
    break;
    }
    。。
      

  13.   

    而且现在我不需要拉升。我做了个和listbox一样的大小的图片。而且listbox也不允许改变大小
      

  14.   


    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    int wmId, wmEvent;
    NOTIFYICONDATA nid;   
    char str[] = "dms server";   
    DWORD dwRet;
    int i, j, k;
    HANDLE *hRecvHandle = NULL;
    HMENU hmenu, hsubmenu;
    char acTmp[MAX_BUFFER_LEN];
    _DMSUSER *usetmp;
    RECT rect, rc; HBITMAP   hBitmap  = (HBITMAP)::LoadImage(NULL,"E:\\XMPP\\dms_im_server\\release\\3.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE); 
    HBRUSH m_brush; switch (message)
    {
    case WM_CTLCOLORLISTBOX:
    {
    GetWindowRect (hEdit, &rc);
    m_brush = CreatePatternBrush(hBitmap);
    HDC   hDC   =   (HDC)wParam; 
    HDC   tempHDC   =   ::CreateCompatibleDC(hDC); 
    HBITMAP   oldBit   =   (HBITMAP)SelectObject(tempHDC,   hBitmap);
    BitBlt(hDC, 0, 0, rc.right-rc.left + 10,  rc.bottom-rc.top + 10,  tempHDC,   0,   0,   SRCCOPY); 
    ::SelectObject(tempHDC,   oldBit);
    DeleteObject((HGDIOBJ)hBitmap);
                return   (LRESULT)m_brush;   
    }
    现在可以了。但是发现内存一直在涨
      

  15.   

    只需要
    case WM_CTLCOLORLISTBOX:
                return   (LRESULT)m_brush;   
    就行了,m_brush在WM_CREATE里创建好,程序退出时释放