用WIN32 API编写自定义BUTTON

用WIN32 API编写自定义BUTTON
    下面分析一下自绘按钮的原理,用过MFC自绘按钮的人都知道,是通过重载了父窗口WM_DRAWITEM的响应消息实现的。同时也要子类化按钮来得到按钮的其他有用的消息,比如WM_MOUSEMOVE、WM_KEYDOWN等消息。因为MFC的消息循环都是封装好的,所以只要派生一下基本控件类就可以了。当是用WIN32API做的话就需要自己来子类化按钮窗口的消息循环了,相信经常编程的朋友都知道,子类化控件要用到SetWindowLong来改变窗口的回调过程,然后在回调窗口内添上自己需要处理的消息即可。因为我们要实现自绘按钮所以最好把子类化的过程做成一个类,然后传给它要自绘的按钮句柄就行了。因为要在类里面实现消息回调函数,但是类里面的消息回调函数只能是静态的,所以不能对应每个实例的消息回调。在我实现的按钮子类化类里,我用到SetProp函数来实现的。要改变BUTTON的特性,必须改变其回调过程,可以通过SetWindowLong、GetWindowLong来实现。
    大家都知道在静态函数中是不能得到其所在类的对象指针,此时可以通过SetProp来记录下对象指针,
SetProp(m_hWnd,"CWINBUTTON",(HANDLE)this)就是记录下这个对象的指针,这样在静态函数中可以通过 CWinButton* cw = (CWinButton*)GetProp(hWnd,"CWINBUTTON");来得到对象的指针,这样就能进行正确的回调。
调用示例:
    bmp = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP));
    win.Init(m_testButton.m_hWnd);//让我们的类改变回调过程
    win.SetBackPic(bmp, TRUE);
参考文章:http://www.vckbase.com/code/listcode.asp?mclsid=3&sclsid=301
    下面只是一个简单的例子改变其背景,说明了这个方法。部分代码如下:
   

// WinButton.h: interface for the CWinButton class.

//

//


#if !defined(AFX_WINBUTTON_H__F55C708D_1059_4AEC_85DA_83243E5D9369__INCLUDED_)
#define AFX_WINBUTTON_H__F55C708D_1059_4AEC_85DA_83243E5D9369__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif
// _MSC_VER > 1000

//#i nclude

#ifdef WIN847
#define DLLPORT __declspec(dllexport)
#else
#define DLLPORT __declspec(dllimport)
#endif

class DLLPORT CWinButton
{
public:
    BOOL SetBackPic(HBITMAP hBitmap,BOOL bReSize);
    BOOL Init(HWND hWnd);
    CWinButton();
    virtual ~CWinButton();
    static LRESULT WINAPI stdProc(HWND hWnd,UINT uMsg,UINT wParam,LONG lParam);
    LRESULT CALLBACK WndProc(UINT message, WPARAM wParam, LPARAM lParam);

private:
    LRESULT OnPaint(HDC hdc);
    HWND m_parenthWnd;
    HWND m_hWnd;//当前的BUTTON句柄
    LONG m_OldProc;
//原来的回调函数地址

    HBITMAP hBackPic;
};

#endif
// !defined(AFX_WINBUTTON_H__F55C708D_1059_4AEC_85DA_83243E5D9369__INCLUDED_)


// WinButton.cpp: implementation of the CWinButton class.

//

//


#include "stdafx.h"
#include "WinButton.h"

//

// Construction/Destruction

//


CWinButton::CWinButton()
{
    
}

CWinButton::~CWinButton()
{

}

BOOL CWinButton::Init(HWND hWnd)
{
    if (IsWindow(hWnd))
    {
        m_hWnd = hWnd;
//托管原来的BUTTON

        m_parenthWnd = GetParent(m_hWnd);
        if (SetProp(m_hWnd,"CWINBUTTON",(HANDLE)this) == 0)
        {
            return FALSE;
        }
        m_OldProc = SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)stdProc);
//改变窗口回调过程

    }
    return FALSE;
}

LRESULT WINAPI CWinButton::stdProc(HWND hWnd,UINT uMsg,UINT wParam,LONG lParam)
{
    CWinButton* cw = (CWinButton*)GetProp(hWnd,"CWINBUTTON");
    return cw->WndProc(uMsg,wParam,lParam);
}
//改变原BUTTON的回调过程

LRESULT CALLBACK CWinButton::WndProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    switch(message)
    {
        case WM_PAINT:
//调用自己设定的刷新

            hdc = BeginPaint(m_hWnd, &ps);
            OnPaint(hdc);
            EndPaint(m_hWnd, &ps);
            break;
    }
    return CallWindowProc((WNDPROC)m_OldProc, m_hWnd, message, wParam, lParam);
//默认回调过程

}
//在这里添加BUTTON的背景设置

LRESULT CWinButton::OnPaint(HDC hdc)
{
    HDC hdcMem,hdcBmp;
    RECT rt;
    int width,height;
    HBITMAP bmp;
    SetBkMode(hdc,TRANSPARENT);
    GetClientRect(m_hWnd,&rt);
    width = rt.right - rt.left;
    height = rt.bottom - rt.top;
    hdcMem = CreateCompatibleDC(hdc);
    hdcBmp = CreateCompatibleDC(hdc);
    SetBkMode(hdcMem,TRANSPARENT);
    bmp = CreateCompatibleBitmap(hdc,width,height);
    SelectObject(hdcMem,bmp);
    if (hBackPic != NULL)
    {
        SelectObject(hdcBmp,hBackPic);
    }
    BitBlt(hdcMem,0,0,width,height,hdcBmp,0,0,SRCCOPY);
    BitBlt(hdc,0,0,width,height,hdcMem,0,0,SRCCOPY);
    DeleteDC(hdcBmp);
    DeleteDC(hdcMem);
    DeleteObject(bmp);
    return TRUE;
}

BOOL CWinButton::SetBackPic(HBITMAP hBitmap, BOOL bReSize)
{
    BITMAP bm;
    RECT rt;
    hBackPic = hBitmap;
    if (hBitmap != NULL)
    {
        if(bReSize)
        {
            GetObject(hBackPic,sizeof(bm),&bm);
            SetWindowPos(m_hWnd,0,0,0,bm.bmWidth,bm.bmHeight,SWP_NOMOVE|SWP_NOREPOSITION);
        }
        GetClientRect(m_hWnd,&rt);
        InvalidateRect(m_hWnd,&rt,TRUE);
        return TRUE;
    }
    return FALSE;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值