win32如何自己编写控件
我最近在学Win32编程,用VC++6.0写的。设计界面的时候,可以拖很多的空间到界面上,然后对相应的空间进行编程。但是我想自己设计控件,如何制作?我想设计一个LED点阵...
我最近在学Win32编程,用VC++6.0写的。设计界面的时候,可以拖很多的空间到界面上,然后对相应的空间进行编程。但是我想自己设计控件,如何制作?我想设计一个LED点阵的空间,或者弄出一个橡皮擦图案的控件,要怎么做?MFC我不懂,有没有用C语言可以做的办法?
展开
3个回答
展开全部
自己做的控件最主要的功能就是接受你发给他的命令,也就是要给外部调用的接口。控件有自己的消息处理函数比如
LRESULT CALLBACK PETextViewWndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
PETextView *View = (PETextView*)GetWindowLong(hWnd,0);
switch(Message)
{
case WM_NCCREATE:
if((View = new PETextView(hWnd)) == 0)
return false;
SetWindowLong(hWnd,0,(LONG)View);
return true;
case WM_NCDESTROY:
if(View)delete View;
return 0;
case WM_PAINT:
return View->OnPaint();
case WM_SIZE:
return View->OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
case PEM_OPENFILE:
return View->OpenFile((TCHAR*)lParam);
case PEM_CLEAR:
return View->ClearFile();
default:
break;
}
return DefWindowProc(hWnd,Message,wParam,lParam);
}
这里有两类消息,一类是系统定义的以WM开头,一类是自己定义的,当然随便你自己定义啦。对应的消息看到是调用相应的函数完成的,这也就是说控件的行为就可以另外编写逻辑部分,然后提供接口给这里调用即可。
之所以说控件就是窗口是因为他有自己的窗口类,以及初始化函数,同时也有创建的函数。窗口类的定义和注册也做成提供给外部的接口,在外部必要的时候调用。而控制控件是通过发送消息来实现的,为了更加好看,可以定义一个宏,比如
#define PE_OpenFile(hWnd, Path) SendMessage((hWnd), PEM_OPENFILE, 0, (LPARAM)(Path))那么创建窗口和控件唯一不同的地方就是,内部的创建和销毁消息是WM_NCCREATE和WM_NCDESTROY,先不管这两个消息。我们看到WM_NCCREATE之前有个GetWindowLong,其内有个SetWindowLong。这两个是关键的,这样就设置了这个控件的属性,使其关联起来,第二个参数msdn上是没有说明设置为0是什么意思的,其实这两个函数的第二个参数设置0表示读取的意思,第一个是读取该控件的属性,然后第二个函数在增加第三个参数的属性的同时读取赋予给这个控件。
一切都OK了!那么控件创建可在外部的WM_CREATE之时调用,当然也可以在使用其功能前调用即可。
一切提供给外部的调用都Port在一个头文件中,这样使用的时候包含这个头文件就好了。
接下来解释那两个消息,这两个消息是因为我们创建了子窗口,也就是我们自己的控件。
这两个消息与WM_CREATE,WM_DESTROY之间的顺序关系是这样的,只看销毁吧。
hwnd = parent, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_NCDESTROY
hwnd = parent, uMsg = WM_NCDESTROY
WM_DESTROY是通知子窗口销毁,然后子窗口通过接受WM_NCDESTROY进行销毁,并发送给父窗口,进行销毁。
细节部分介绍的差不多,总体思路就是和创建窗口差不多,但是要搞个头文件,把一些个常量和功能的函数另外一个窗口类的初始化和创建的接口搞进去。
LRESULT CALLBACK PETextViewWndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
PETextView *View = (PETextView*)GetWindowLong(hWnd,0);
switch(Message)
{
case WM_NCCREATE:
if((View = new PETextView(hWnd)) == 0)
return false;
SetWindowLong(hWnd,0,(LONG)View);
return true;
case WM_NCDESTROY:
if(View)delete View;
return 0;
case WM_PAINT:
return View->OnPaint();
case WM_SIZE:
return View->OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
case PEM_OPENFILE:
return View->OpenFile((TCHAR*)lParam);
case PEM_CLEAR:
return View->ClearFile();
default:
break;
}
return DefWindowProc(hWnd,Message,wParam,lParam);
}
这里有两类消息,一类是系统定义的以WM开头,一类是自己定义的,当然随便你自己定义啦。对应的消息看到是调用相应的函数完成的,这也就是说控件的行为就可以另外编写逻辑部分,然后提供接口给这里调用即可。
之所以说控件就是窗口是因为他有自己的窗口类,以及初始化函数,同时也有创建的函数。窗口类的定义和注册也做成提供给外部的接口,在外部必要的时候调用。而控制控件是通过发送消息来实现的,为了更加好看,可以定义一个宏,比如
#define PE_OpenFile(hWnd, Path) SendMessage((hWnd), PEM_OPENFILE, 0, (LPARAM)(Path))那么创建窗口和控件唯一不同的地方就是,内部的创建和销毁消息是WM_NCCREATE和WM_NCDESTROY,先不管这两个消息。我们看到WM_NCCREATE之前有个GetWindowLong,其内有个SetWindowLong。这两个是关键的,这样就设置了这个控件的属性,使其关联起来,第二个参数msdn上是没有说明设置为0是什么意思的,其实这两个函数的第二个参数设置0表示读取的意思,第一个是读取该控件的属性,然后第二个函数在增加第三个参数的属性的同时读取赋予给这个控件。
一切都OK了!那么控件创建可在外部的WM_CREATE之时调用,当然也可以在使用其功能前调用即可。
一切提供给外部的调用都Port在一个头文件中,这样使用的时候包含这个头文件就好了。
接下来解释那两个消息,这两个消息是因为我们创建了子窗口,也就是我们自己的控件。
这两个消息与WM_CREATE,WM_DESTROY之间的顺序关系是这样的,只看销毁吧。
hwnd = parent, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_NCDESTROY
hwnd = parent, uMsg = WM_NCDESTROY
WM_DESTROY是通知子窗口销毁,然后子窗口通过接受WM_NCDESTROY进行销毁,并发送给父窗口,进行销毁。
细节部分介绍的差不多,总体思路就是和创建窗口差不多,但是要搞个头文件,把一些个常量和功能的函数另外一个窗口类的初始化和创建的接口搞进去。
展开全部
可以!!!
首先要相信,只有你想不到,没有你做不到。VC博大精神。。。
现在就说一下我的思路:
1、首先要远程注入,因为这是跨进程的访问数据,因此,如果不注入的话,是很难从一个进程直接访问另一个进程的空间的,因为每个进程都有自己私有的4G空间。注入的方法很多,不说了。
2、枚举所有的浏览器子窗口。EnumChildWindow
3、监测枚举到的子窗口,获得其注册名字(classname),由此判断是不是一个Edit控件。如果是一个edit控件,则获得它的风格,如果有PASSWORD风格,则说明是一个密码输入框。
4、使用SendMessage( WM_GETTEXT )等函数获得Edit框中的文本。
5、搞定。
另外,至于要判断是不是处于焦点,更简单了。
使用上面第3步得到的Edit句柄,去判断GetFocus()是不是相等。就知道了。
还有,第一步非常重要,否则,余下的都不能实现。
首先要相信,只有你想不到,没有你做不到。VC博大精神。。。
现在就说一下我的思路:
1、首先要远程注入,因为这是跨进程的访问数据,因此,如果不注入的话,是很难从一个进程直接访问另一个进程的空间的,因为每个进程都有自己私有的4G空间。注入的方法很多,不说了。
2、枚举所有的浏览器子窗口。EnumChildWindow
3、监测枚举到的子窗口,获得其注册名字(classname),由此判断是不是一个Edit控件。如果是一个edit控件,则获得它的风格,如果有PASSWORD风格,则说明是一个密码输入框。
4、使用SendMessage( WM_GETTEXT )等函数获得Edit框中的文本。
5、搞定。
另外,至于要判断是不是处于焦点,更简单了。
使用上面第3步得到的Edit句柄,去判断GetFocus()是不是相等。就知道了。
还有,第一步非常重要,否则,余下的都不能实现。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐于2016-04-29 · 知道合伙人互联网行家
关注
展开全部
创建ActiveX控件的步骤:
创建一个类,实现IOleClientSite和IOleInPlaceSite。
使用CoCreateInstance创建相应ActiveX控件的实例,并获取它的IOleObject接口指针。
调用IOleObject::SetClientSite传入第一步中的类的指针。
调用IOleObject::DoVerb完成ActiveX控件的创建。
之后,可以调用ActiveX控件的IOleInPlaceObject::SetObjectRects调整控件的大小和位置。
创建一个类,实现IOleClientSite和IOleInPlaceSite。
使用CoCreateInstance创建相应ActiveX控件的实例,并获取它的IOleObject接口指针。
调用IOleObject::SetClientSite传入第一步中的类的指针。
调用IOleObject::DoVerb完成ActiveX控件的创建。
之后,可以调用ActiveX控件的IOleInPlaceObject::SetObjectRects调整控件的大小和位置。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询