首页 > Windows开发 > 详细

WIN32窗口子类化----自定义Edit控件的右键菜单

时间:2015-03-28 21:47:08      阅读:549      评论:0      收藏:0      [点我收藏+]

前言


Win32应用程序中,子控件的消息都是分发到其父窗口的消息处理函数中去了,这对于我们需要自定义子控件的某些特性时时十分不方便的,还好,Windows为我们提供了控件子类化的相关接口API。核心的思想是:通过获取子控件的消息处理函数地址,设置子控件的消息处理函数到自己定义的函数里,也就是Get/SetWindowLong API的使用。


测试代码


这里是一个简单的测试程序,在控制台程序中创建一个对话框,然后对话框上有一个EDIT控件(资源编辑器里拖入的,不多说),子类化EDIT控件,右键弹出自己的菜单屏蔽系统默认的菜单。

#include <crtdbg.h>
#include <Windows.h>
#include <WindowsX.h>
#include <CommCtrl.h>
#include "resource.h"
HWND	g_hEditWnd;
WNDPROC	g_pOldProc;
HINSTANCE	g_hInst;

INT_PTR CALLBACK DlgMessageProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK EditMessageProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int _tmain(int argc, _TCHAR* argv[])
{
	g_hInst = (HINSTANCE)::GetModuleHandle(NULL);
	::LoadLibrary(L"riched20.dll");
	DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgMessageProc);
	_CrtDumpMemoryLeaks();
	//system("ipconfig");
	system("pause");
	return 0;
}

INT_PTR CALLBACK DlgMessageProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch( uMsg )
	{
	case WM_INITDIALOG:
		{
			::SetWindowText(hDlg, L"控制台测试程序:");
			g_hEditWnd = ::GetDlgItem(hDlg, IDC_EDIT1);
			g_pOldProc = (WNDPROC)::GetWindowLong(g_hEditWnd, GWL_WNDPROC);
			::SetWindowLong(g_hEditWnd, GWL_WNDPROC, (LONG)EditMessageProc);
			//::SetWindowSubclass(g_hEditWnd, )
			return TRUE;
		}
	}
	return ::DefWindowProc(hDlg, uMsg, wParam, lParam);
}

LRESULT CALLBACK EditMessageProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch( uMsg )
	{
	case WM_RBUTTONUP:
		{
			HMENU hMenu = ::LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU1));
			HMENU hPopMenu = ::GetSubMenu(hMenu, 0);
			POINT pt; 
			::GetCursorPos(&pt);
			::SetForegroundWindow(hWnd);
			DWORD dwBegin, dwEnd;
			::SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwBegin, (LPARAM)&dwEnd);
			BOOL bCanUndo = ::SendMessage(hWnd, EM_CANUNDO, 0, 0);
			if ( dwEnd == dwBegin )
			{
				::ModifyMenu(hPopMenu, ID_EDITMENU_CUT, MF_BYCOMMAND|MF_GRAYED, ID_EDITMENU_CUT, L"剪切    Ctrl + X");
				::ModifyMenu(hPopMenu, ID_EDITMENU_COPY, MF_BYCOMMAND|MF_GRAYED, ID_EDITMENU_COPY, L"复制    Ctrl + C");
				::ModifyMenu(hPopMenu, ID_EDITMENU_DEL, MF_BYCOMMAND|MF_GRAYED, ID_EDITMENU_DEL, L"删除    Ctrl + D");
			}
			if ( !bCanUndo )
			{
				::ModifyMenu(hPopMenu, ID_EDITMENU_UNDO, MF_BYCOMMAND|MF_GRAYED, ID_EDITMENU_UNDO, L"撤销    Ctrl + U");
			}
			::TrackPopupMenu(hPopMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
			::DestroyMenu(hMenu);
			return TRUE;
		}
	case WM_COMMAND:
		{
			WORD wHigh	= HIWORD(wParam);
			WORD wLow	= LOWORD(wParam);
			if ( wHigh == 0 )
			{//菜单消息
				switch( wLow )
				{
				case ID_EDITMENU_CUT:
					{//剪切
						::SendMessage(hWnd, WM_CUT, 0, 0);
						break;
					}
				case ID_EDITMENU_COPY:
					{//复制
						::SendMessage(hWnd, WM_COPY, 0, 0);
						break;
					}
				case ID_EDITMENU_PASTE:
					{//粘贴
						::SendMessage(hWnd, WM_PASTE, 0, 0);
						break;
					}
				case ID_EDITMENU_SELALL:
					{//全选
						::SendMessage(hWnd, EM_SETSEL, 0, -1);
						break;
					}
				case ID_EDITMENU_UNDO:
					{//撤销
						::SendMessage(hWnd, WM_UNDO, 0, 0);
						break;
					}
				case ID_EDITMENU_DEL:
					{//全选
						::SendMessage(hWnd, WM_CLEAR, 0, 0);
						break;
					}
				}
			}
			break;
		}
	default:
		break;
	}
	//把消息处理交还给默认消息处理函数
	return g_pOldProc(hWnd, uMsg, wParam, lParam);
}

处理WM_RBUTTONUP消息,弹出我们自己的菜单同时函数返回,不去调用默认消息处理函数默认菜单也就不会弹出来了。

菜单的点击消息都是用WM_COMMAND消息发送给菜单的父窗口的(在创建菜单时传入的那个窗口句柄),HIWORD(wParam)为0的时候就是菜单的消息了,详细的看MSDN就知道了。

另外,除了这些消息,其他的消息都要调用默认消息函数处理,不然的话EDIT控件是画不出来的。


关键地方:

<span style="white-space:pre">			</span>g_hEditWnd = ::GetDlgItem(hDlg, IDC_EDIT1);
			g_pOldProc = (WNDPROC)::GetWindowLong(g_hEditWnd, GWL_WNDPROC);
			::SetWindowLong(g_hEditWnd, GWL_WNDPROC, (LONG)EditMessageProc);
WM_INITDIALOG在对话框的初始化消息中获取EDIT的句柄,然后GetWindowLong保存原来的消息处理函数指针,SetWindowLong来设置消息到我们的处理函数中。

至于标准EDIT控件中的复制、粘贴、剪切……等处理在Windows中都已经提供了消息处理,我们只需要发送对应的消息到EDIT控件就好了,不用去计算文字选中等复杂过程。


运行截图:



技术分享


WIN32窗口子类化----自定义Edit控件的右键菜单

原文:http://blog.csdn.net/mfcing/article/details/44706227

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!