首页
论坛
课程
招聘
[原创]利用子类化技术拓展EDIT控(7.26最近更新)
2005-7-24 18:30 9069

[原创]利用子类化技术拓展EDIT控(7.26最近更新)

2005-7-24 18:30
9069
HTML文档:利用子类化技术拓展EDIT控件功能

附件:利用子类化技术拓展EDIT控件功能(7.26最近更新)
请管理员删除上面的旧链接

利用子类化技术拓展EDIT控件功能

前言:EDIT控件提供的“Number”属性往往无法满足要求,它只能接受数字输入,而经常要需求只接受16进制输入。可以用多种方法(子类化技术,钩子函数,开辟新线程),这里选择子类化技术。

一。认识子类化技术

    把一个窗体子类化其实就是使用SetWindowLong为该窗体设计一个新的窗体过程,然后可以在该窗体函数中处理特定的消息,而那些不关心的消息可以通过CallWindowProc传递给系统默认的处理。(有关这方面的介绍网上很多,不过多介绍)

    从功能上来说,子类化技术有点类似于钩子函数(SetWindowHookEx),都可以对一些特定的消息自由处理。但在两者有着本质的区别,钩子函数是针对系统的消息传递机制,而子类化技术则是针对特定的窗体。利用钩子函数可以处理某一类或几类的消息,而利用子类化技术则能处理特定窗体的绝大部分消息。因而在使用时应区分被处理对象的范围,然后再选择采用哪种技术。

二。体验子类化技术

资源模板:一个对话框(IDD_TEST_SAMPLE)和一个EDIT控件(IDC_TEST).

测试程序 (程序简单,不作介绍):
#include "resource.h"
#include <TChar.h>
#include <windows.h>

/**********************************
*  Global variable
***********************************/

LONG DefWndProc = NULL ;

/**********************************
*  Sub function pre-definition
***********************************/

LRESULT CALLBACK EditNewProc ( HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam ) ;
BOOL CALLBACK TestSampleProc ( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) ;

/**********************************
*  main function
***********************************/

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
        // TODO: Place code here.
        DialogBox ( hInstance, MAKEINTRESOURCE(IDD_TEST_SAMPLE), 0, TestSampleProc ) ;

        return 0;
}

/**********************************
*  Detail of sub function
***********************************/

LRESULT CALLBACK EditNewProc ( HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
        return CallWindowProc ( (WNDPROC)DefWndProc, hEdit, uMsg, wParam, lParam ) ;
}

BOOL CALLBACK TestSampleProc ( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{       
        LONG DlgWndProc, EditWndProc ;
        TCHAR buf[128] ;

        switch ( message )
        {
        case WM_INITDIALOG:
                DlgWndProc = GetWindowLong ( hDlg, GWL_WNDPROC ) ;
                EditWndProc = GetWindowLong ( GetDlgItem(hDlg,IDC_TEST), GWL_WNDPROC ) ;
                       
                wsprintf ( buf, _TEXT("DlgWndProc  : %08X\nEditWndProc : %08X\nDefWndProc:%08X\n"), \
                        DlgWndProc, EditWndProc, DefWndProc ) ;
                MessageBox ( hDlg, buf, _TEXT("子类化之前"), 0 ) ;

                DefWndProc = SetWindowLong (
                        GetDlgItem(hDlg,IDC_TEST), GWL_WNDPROC, (long)EditNewProc ) ;
                return true ;

        case WM_COMMAND:
                switch ( LOWORD(wParam) )
                {
                case IDCANCEL:
                        EndDialog ( hDlg, 0 ) ;
                        return true ;
                }
                break ;

        case WM_LBUTTONDOWN:
                DlgWndProc = GetWindowLong ( hDlg, GWL_WNDPROC ) ;
                EditWndProc = GetWindowLong ( GetDlgItem(hDlg,IDC_TEST), GWL_WNDPROC ) ;
                       
                wsprintf ( buf, _TEXT("DlgWndProc  : %08X\nEditWndProc : %08X\nDefWndProc:%08X\n"), \
                        DlgWndProc, EditWndProc, DefWndProc ) ;
                MessageBox ( hDlg, buf, _TEXT("子类化之后"), 0 ) ;

                return false ;
        }

        return false ;
}
测试结果 :

测试说明 :左图==》DlgWndProc和EditWndProc实际上就是系统默认的对话框处理函数体和
                    编辑框处理函数体。DefWndProc是用来保存编辑框的默认处理函数的入口,
                          程序中把它初始化为0。
            右图==》DefWndProc保存了系统默认的编辑框处理函数体;
                    EditWndProc即为新添加的函数的入口地址。
三。进入主题--EDIT功能拓展
功能需求 :1)。输入字符个数不大于8
           2)。可输入的合法字符(0--9,A--F,a--f)
设计概要 :
1)。由于EDIT功能拓展需要处理是字符,所以选择处理的对象为
WM_CHAR :     TCHAR chCharCode = (TCHAR) wParam ; // character code
2)。确保用户输入的字符的合法性
if ( ( chCharCode >= 0X30 && chCharCode <= 0X39 ) || \     ( chCharCode >= 0X41 && chCharCode <= 0X46 ) || \     ( chCharCode >= 0X61 && chCharCode <= 0X66 )  ){              //合法            }
3)。保证EDIT中的字符个数不大于8
TCHAR tEditText[9] ;
int iCharacterNum = GetWindowText ( hEdit, tEditText, sizeof(tEditText)/sizeof(TCHAR) ) ;
if ( iCharacterNum < 8 )
{
        //符合要求,继续接受字符
}
else
{
         //不符合要求,忽略键盘消息(不处理)}
4)。必须保证退格键能够正常运行
if ( chCharCode == _TEXT(8) )
        return CallWindowProc ( (WNDPROC)DefWndProc, hEdit, uMsg, wParam, lParam ) ;
注:退格键的ASCII值为8
详细设计(源代码--VC):
#include "resource.h"
#include <TChar.h>
#include <windows.h>
/**********************************
*  Global variable
***********************************/

LONG DefWndProc = NULL ;

/**********************************
*  Sub function pre-definition
***********************************/

LRESULT CALLBACK EditNewProc ( HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam ) ;
BOOL CALLBACK TestSampleProc ( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) ;

/**********************************
*  main function
***********************************/

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
        DialogBox ( hInstance, MAKEINTRESOURCE(IDD_TEST_SAMPLE), 0, TestSampleProc ) ;

        return 0;
}

/**********************************
*  Detail of sub function
***********************************/
注:如果使用EDIT控件时不需要“窗体过程切换”,可以把下面这段EditNewProc直接使用,不然可以使用下一部分的DLL 。

LRESULT CALLBACK EditNewProc ( HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
        if ( uMsg == WM_CHAR )
        {
                TCHAR chCharCode = (TCHAR) wParam ;

                if ( ( chCharCode >= 0X30 && chCharCode <= 0X39 ) || \
                     ( chCharCode >= 0X41 && chCharCode <= 0X46 ) || \
                     ( chCharCode >= 0X61 && chCharCode <= 0X66 )  )
                {
                        TCHAR tEditText[9] ;

                        int iCharacterNum = GetWindowText ( hEdit, tEditText, sizeof(tEditText)/sizeof(TCHAR) ) ;

                        if ( iCharacterNum < 8 )
                        {
                                MessageBeep ( MB_OK ) ;
                        }
                        else
                                return NULL ;
                }

                else if ( chCharCode == _TEXT(8) )
                        return CallWindowProc ( (WNDPROC)DefWndProc, hEdit, uMsg, wParam, lParam ) ;

                else
                        return NULL ;
        }

        return CallWindowProc ( (WNDPROC)DefWndProc, hEdit, uMsg, wParam, lParam ) ;
}

BOOL CALLBACK TestSampleProc ( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{       
        switch ( message )
        {
        case WM_INITDIALOG:
                DefWndProc = SetWindowLong (
                        GetDlgItem(hDlg,IDC_TEST), GWL_WNDPROC, (long)EditNewProc ) ;
                return true ;

        case WM_COMMAND:
                switch ( LOWORD(wParam) )
                {
                case IDCANCEL:
                        EndDialog ( hDlg, 0 ) ;
                        return true ;
                }
                break ;
        }

        return false ;
}
说明:当用户按键有效时会产生系统提示音。
四。DLL--功能封装

接口函数 :

BOOL WINAPI SetExternEditFunction (
        BOOL isSet,       //是否处于拓展状态(切换窗体过程)
        HWND hParent,     //父窗口句柄
        UINT dwEditId     //EDIT控件ID
) ;

最重要的功能实现 EditNewProc 与 EditDefWndProc 这两个EDIT窗体过程之间的切换。

附:DLL源码( WINXPSP2,VC6.0,WIN32 DLL )

五:功能更新

7.26更新:支持WM_COPY, WM_CUT, WM_PASTE .

说明:前两个功能比较简单,重点是WM_PASTE.

WM_PASTE功能实现的简略介绍:

1)。取得粘贴板中可复制的合法字串,

2)。检测该字串的长度,若过长则截去多余部分

3)。检测剩余字符串的合法性

4)。模拟键盘消息实现:在鼠标所指向的位置增添字符。

例:EDIT中已有字符串“123Iabc"(‘I’表示鼠标位置)

需要拷贝的字符串“defghijk"

===》 “123deabc"

----------------------------------------------------------------------------------                           
作者 :北极星2003
邮箱 :zhangjingsheng_nbu@yahoo.com.cn

注:转载请保持文章完整


[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞0
打赏
分享
最新回复 (7)
雪    币: 4656
活跃值: 活跃值 (11830)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2005-7-24 18:47
2
0
谢谢分享!
编辑了一下你的帖子,将压缩包中的Html文档帖出来了,主要方便以后论坛资料搜索。
雪    币: 46932
活跃值: 活跃值 (170301)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 活跃值 2005-7-24 19:03
3
0
支持先
雪    币: 1613
活跃值: 活跃值 (38)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 活跃值 25 2005-7-24 19:18
4
0
最初由 kanxue 发布
谢谢分享!
编辑了一下你的帖子,将压缩包中的Html文档帖出来了,主要方便以后论坛资料搜索。


麻烦老大了
雪    币: 201
活跃值: 活跃值 (11)
能力值: ( LV9,RANK:770 )
在线值:
发帖
回帖
粉丝
kyc 活跃值 19 2005-7-24 21:20
5
0
good
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
ttui 活跃值 6 2005-7-24 23:11
6
0
还应该处理WM_PASTE监视粘贴的数据
雪    币: 1141
能力值: (RANK:460 )
在线值:
发帖
回帖
粉丝
monkeycz 活跃值 11 2005-7-25 10:09
7
0
不错
雪    币: 1613
活跃值: 活跃值 (38)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 活跃值 25 2005-7-25 17:35
8
0
最初由 ttui 发布
还应该处理WM_PASTE监视粘贴的数据


多谢提醒,有待改进
游客
登录 | 注册 方可回帖
返回