.NET Windows Form 改变窗体类名(Class Name)有多难?
研究WinForm的东西,是我的一个个人兴趣和爱好,以前做的项目,多与WinForm相关,然而这几年,项目都与WinForm没什么关系了,都转为ASP.NET MVC与WPF了。关于今天讨论的这个问题,以前也曾深入研究过,只是最近有朋友问到这个问题,就再挖挖这个坟(坑)。
一、类名是啥?打开神器SPY++,VS2013 在【工具】菜单里:
VS2013之前的VS版本,在【开始菜单】里:
打开SPY++,点击标注的按钮,
在打开的窗口上,把雷达按钮拖到你想查看的窗口,就可以看到它的类名了,下面就是QQ的类名:
再看看.NET WinForm的窗体类名:
一大串啊,有没有,我不想这样,我想要一个有个性的、简单的类名,咋办?
二、 不是有个CreateParams属性吗?作为一个有多年WinForm开发经验的程序猿,这有啥难的,WinForm的控件不是都有个CreateParams属性吗?里面可以不是就可以设置窗口类名吗?看看:
真的有,这不就简单了嘛,动手,于是有下面代码:
public partial class FormMain : Form { public FormMain() { InitializeComponent(); } protected override CreateParams CreateParams { get { CreateParams createParams = base.CreateParams; createParams.ClassName = "Starts2000.Window"; //这就是我想要的窗体类名。 return createParams; } } }
编译,运行,结果却是这样的:
泥煤啊,这是什么啊,翻~墙,一通谷歌,原来类名使用前都需要注册啊,难道微软只注册了自己的类名,我个性化的他就不帮我注册,那我就自己注册吧,坑爹的微软啊。
三、注册一个窗口类名吧注册窗口类名需要用到Windows API函数了,用C#进行P/Invoke?太麻烦了,做了这么多年的WinForm开发,我可是练了《葵花宝典(C++/CLI)》的,只是因为没自宫,所以没大成,不过,简单用用还是可以的。
创建一个C++空项目,设置项目属性-配置属性-常规,如下图:
于是有了下面的代码:
1. FormEx.h
#pragma once #include <Windows.h> #include <vcclr.h> #define CUSTOM_CLASS_NAME L"Starts2000.Window" namespace Starts2000 { namespace WindowsClassName { namespace Core { using namespace System; using namespace System::Windows::Forms; using namespace System::Runtime::InteropServices; private delegate LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); public ref class FormEx : public Form { public: static FormEx(); FormEx(); private: static LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static void ProcessExit(Object^ sender, EventArgs^ e); }; } } }
2. FormEx.cpp
#include "FormEx.h" namespace Starts2000 { namespace WindowsClassName { namespace Core { static FormEx::FormEx() { WNDCLASSEX wc; Starts2000::WindowsClassName::Core::WndProc ^windowProc = gcnew Starts2000::WindowsClassName::Core::WndProc(FormEx::WndProc); pin_ptr<Starts2000::WindowsClassName::Core::WndProc^> pWindowProc = &windowProc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_DBLCLKS; wc.lpfnWndProc = reinterpret_cast<WNDPROC>(Marshal::GetFunctionPointerForDelegate(windowProc).ToPointer()); wc.hInstance = GetModuleHandle(NULL); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; //(HBRUSH)GetStockObject(HOLLOW_BRUSH); wc.lpszClassName = CUSTOM_CLASS_NAME; ATOM classAtom = RegisterClassEx(&wc); DWORD lastError = GetLastError(); if (classAtom == 0 && lastError != ERROR_CLASS_ALREADY_EXISTS) { throw gcnew ApplicationException("Register window class failed!"); } System::AppDomain::CurrentDomain->ProcessExit += gcnew System::EventHandler(FormEx::ProcessExit); } FormEx::FormEx() : Form() { } LRESULT FormEx::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { System::Windows::Forms::Message message = System::Windows::Forms::Message::Create((IntPtr)hWnd, (int)msg, (IntPtr)((void*)wParam), (IntPtr)((void*)lParam)); System::Diagnostics::Debug::WriteLine(message.ToString()); return DefWindowProc(hWnd, msg, wParam, lParam); } void FormEx::ProcessExit(Object^ sender, EventArgs^ e) { UnregisterClass(CUSTOM_CLASS_NAME, GetModuleHandle(NULL)); } } } }
3. 创建一个C# WinForm项目,引用上面创建的C++/CLI项目生成的DLL,代码跟最开始的区别不大。
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/67639.html