首页 IP地址查询 | Alexa排名查询 | 手机归属地查询
设为首页 收藏本站
  • 网络编程网络编程
  • 软件编程软件编程
  • 数据库技术数据库技术
  • 编程学院
  • 业界资讯 业界资讯
  • 源码中心源码中心
  • 会员中心会员中心
  • 页面导航: 首页MFC组件控钮 → 用 Win API 实现自绘按钮类

    用 Win API 实现自绘按钮类

    发布:颜飞 发布日期:2008-01-19 字体:[增加 减小] 类型:转载

    下载源代码

    下面分析一下自绘按钮的原理,用过mfc自绘按钮的人都知道,是通过重载了父窗口wm_drawitem的响应消息实现的。同时也要子类化按钮来得到按钮的其他有用的消息,比如wm_mousemove、wm_keydown等消息。因为mfc的消息循环都是封装好的,所以只要派生一下基本控件类就可以了。当是用win32api做的话就需要自己来子类化按钮窗口的消息循环了,相信经常编程的朋友都知道,子类化控件要用到setwindowlong来改变窗口的回调过程,然后在回调窗口内添上自己需要处理的消息即可。因为我们要实现自绘按钮所以最好把子类化的过程做成一个类,然后传给它要自绘的按钮句柄就行了。因为要在类里面实现消息回调函数,但是类里面的消息回调函数只能是静态的,所以不能对应每个实例的消息回调。在我实现的按钮子类化类里,我用到thunk技术或setprop函数来实现的,具体请网上查找。

      下面我来谈谈自绘按钮里最重要的部分,就是响应按钮消息函数里的wm_paint消息,我们所有的自绘动作都在这里进行的。wm_paint里的绘图操作与普通窗口的操作一样,但是为了跟踪按钮的当前状态,我们还要响应按钮窗口的wm_mousemove、wm_setfocus、wm_killfocus、wm_lbuttondown、wm_enable等消息来得到当前按钮的状态。从而在wm_paint里面绘出不同的状态,能实现的东西很多可以说你想多少基本就能实现多少^_^,看个人喜好了,我提供源代码大家可以自行修改。我也是参看了buttonst里面自绘的代码,我自己添加了右键拖动功能,鼠标掠过发生功能大家有兴趣可以自己添加,锻炼一下自己的编程能力^_^。

      下面我说一下我做的这个类的一个问题,我把按钮类做成了一个动态库,调用时只要加上我的头文件和连接的lib库就可以了。我的动态库在win32的程序加载是没有问题的,但是在mfc里面,必需要响应父窗口的wm_drawitem消息,在里面直接返回,而不要调用mfc默认的处理就ok了。这是因为我没有截获父窗口的wm_drawitem消息,否则在关闭程序时会出现非法操作!主要代码分析如下:

    自绘按钮类声明:

    class dllport cwinbutton 
    {
    public:
     //初始化按钮(这是第一步!)
     bool getitemhwnd(hwnd hwnd);
     //还原按钮区域设置
     bool restore();
     //设置按钮是否可以拖动
     bool setdrag(bool enable);
     //设置按钮图标
     bool seticon(hicon icon);
     //设置按钮文字
     bool settext(char *text, hfont font);
     bool settext(char *text);
     bool settext(char *text, colorref color);
     //设置按钮有效区域
     bool setupregion(colorref transcolor);
     lresult onpaint(hdc hdc);
     //设置按钮无效时的图片
     bool setdisablepic(hbitmap bmp);
     //设置按钮按下时的图片
     bool setpresspic(hbitmap bmp);
     //设置悬停按钮时的图片
     bool sethoverpic(hbitmap bmp);
     //设置按钮背景图片,第二个参数是是否根据图片调整按钮大小
     bool setbackpic(hbitmap bmp, bool bresize);
     //设置按钮的提示消息
     bool settooltip(char *text);
     cwinbutton();
     virtual ~cwinbutton();
     
    private:
     static lresult winapi stdproc(hwnd hwnd,uint umsg,uint wparam,long lparam);
     wndproc getthunk();
     wndproc createthunk();
     lresult callback winproc(uint message, wparam wparam, lparam lparam);
     bool drawinsideborder(hdc dc, rect *rect);
     bool drawflat(hdc dc, rect *rect);
     bool drawdefault(hdc dc);
     hwnd m_tooltip;
     hwnd m_hwnd;
     hwnd m_hwndparent;
     long m_oldproc;
     wndproc m_thunk;
     toolinfo ti;
     hicon m_icon;
     hbitmap m_back; //按钮背景图片
     hbitmap m_hove; //鼠标悬停时按钮背景图片
     hbitmap m_press; //鼠标按下时按钮背景图片
     hbitmap m_disable; //按钮无效时背景图片
     bitmap bm;
     colorref m_textcolor; //按钮文字的颜色
     bool m_bmousetracking; //判断鼠标是否在窗口内
     bool m_bpress; //判断鼠标是否按下
     bool m_enable; //控件是否有效
     bool m_bfocus; //按钮是否处于输入焦点
     bool m_bownerdraw; //判断是否用户自己贴图
     bool m_bdrag; //是否处于拖动状态
     bool m_bdragenable; //是否允许拖动
     char m_text[max_textlen]; //按钮文字
     char m_tiptext[max_textlen]; //按钮提示文字
     hfont m_font; //按钮文字字体
     hcursor m_oldcursor;
     rect m_parentrt;
     rect m_beginrt;
     rect m_currentrt;
     point m_beginpt;
     point m_currentpt;
     int m_captionheight;
     int m_borderwidth;
     int m_edgewidth;
     
    protected:
     //按钮的外边框
     hpen m_boundrypen;
     
     //鼠标指针置于按钮之上时按钮的内边框
     hpen m_insideboundrypenleft;
     hpen m_insideboundrypenright;
     hpen m_insideboundrypentop;
     hpen m_insideboundrypenbottom;
     
     //按钮获得焦点时按钮的内边框
     hpen m_insideboundrypenleftsel;
     hpen m_insideboundrypenrightsel;
     hpen m_insideboundrypentopsel;
     hpen m_insideboundrypenbottomsel;
     
     //按钮的底色,包括有效和无效两种状态
     hbrush m_fillactive;
     hbrush m_fillinactive;
    };
    

    消息回调类里的实现代码:

    cwinbutton::getitemhwnd()里面
    
    if(setprop(m_hwnd, "cwinbutton", (handle)this) == 0)
    {
     outputdebugstring("setprop error");
     return false;
    }
    
    m_oldproc = setwindowlong(m_hwnd,gwl_wndproc,(long)stdproc);
    
    cwinbutton::stdproc()里面
    {
     cwinbutton* w = (cwinbutton*)getprop(hwnd, "cwinbutton");
     return w->winproc(umsg,wparam,lparam);
    }

    Tags: Button 自绘 mfc api
    为配合网络严查,文章评论将关闭敬请谅解.
    同 类 文 章
    最 近 更 新
    热 点 排 行