首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何自定义Windows窗体的系统菜单?

如何自定义Windows窗体的系统菜单?
EN

Stack Overflow用户
提问于 2019-04-16 03:12:26
回答 1查看 322关注 0票数 0

我想将“关于”菜单添加到我的应用程序标题栏的上下文菜单中。

我在互联网上进行了多次搜索,找到了这个很棒的主题How can I customize the system menu of a Windows Form?,但没有针对visual C++的解决方案。我试着从所提到的主题中调整解决方案,但出现了一些问题。我可以看到一些新的东西出现在上下文菜单中,但没有“关于”项。

下面是我的代码:

代码语言:javascript
复制
#pragma once
#include <string>

namespace context_menu {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Runtime::InteropServices;
    using std::string;

    // P/Invoke constants
    const int WM_SYSCOMMAND = 0x112;
    const int MF_STRING = 0x0;
    const int MF_SEPARATOR = 0x800;

    // P/Invoke declarations
    [DllImport("user32.dll", CharSet = System::Runtime::InteropServices::CharSet::Auto, SetLastError = true)]
    extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll", CharSet = System::Runtime::InteropServices::CharSet::Auto, SetLastError = true)]
    extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);

    [DllImport("user32.dll", CharSet = System::Runtime::InteropServices::CharSet::Auto, SetLastError = true)]
    extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);


    /// <summary>
    /// Summary for Form1
    ///
    /// WARNING: If you change the name of this class, you will need to change the
    ///          'Resource File Name' property for the managed resource compiler tool
    ///          associated with all .resx files this class depends on.  Otherwise,
    ///          the designers will not be able to interact properly with localized
    ///          resources associated with this form.
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    // ID for the About item on the system menu
    private: static int SYSMENU_ABOUT_ID = 0x1;
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->SuspendLayout();
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(284, 261);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);
        }
#pragma endregion

    protected: virtual System::Void OnHandleCreated( System::EventArgs^ e ) override {
                System::Windows::Forms::Form::OnHandleCreated( e );
                // Get a handle to a copy of this form's system (window) menu
                IntPtr sysMenuHandle = GetSystemMenu( this->Handle, false );
                // Add a separator
                AppendMenu( sysMenuHandle, MF_SEPARATOR, 0, "" );
                // Add the About menu item
                AppendMenu( sysMenuHandle, MF_STRING, SYSMENU_ABOUT_ID, "&About…\n" );
            }

    protected: virtual System::Void WndProc( Message % m ) override {
                System::Windows::Forms::Form::WndProc( m );
                // Show test message
                if( ( m.Msg == WM_SYSCOMMAND ) && ( (int)m.WParam == SYSMENU_ABOUT_ID ) )
                {
                    MessageBox::Show( "Custom About Dialog" );
                }
            }
    };
}

这是我的result

编辑

根据@David Yaw answer的说法,我添加了#include <Windows.h>,并删除了所有不必要的代码。我需要解决一些小问题,过了一段时间它就被解决了。但随后出现了链接器错误:

代码语言:javascript
复制
1>context_menu.obj : error LNK2028: unresolved token (0A00001A) "extern "C" int __stdcall AppendMenuW(struct HMENU__ *,unsigned int,unsigned int,wchar_t const *)" (?AppendMenuW@@$$J216YGHPAUHMENU__@@IIPB_W@Z) referenced in function "protected: virtual void __clrcall context_menu::Form1::OnHandleCreated(class System::EventArgs ^)" (?OnHandleCreated@Form1@context_menu@@$$FM$AAMXP$AAVEventArgs@System@@@Z)
1>context_menu.obj : error LNK2028: unresolved token (0A00001B) "extern "C" struct HMENU__ * __stdcall GetSystemMenu(struct HWND__ *,int)" (?GetSystemMenu@@$$J18YGPAUHMENU__@@PAUHWND__@@H@Z) referenced in function "protected: virtual void __clrcall context_menu::Form1::OnHandleCreated(class System::EventArgs ^)" (?OnHandleCreated@Form1@context_menu@@$$FM$AAMXP$AAVEventArgs@System@@@Z)
1>context_menu.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall AppendMenuW(struct HMENU__ *,unsigned int,unsigned int,wchar_t const *)" (?AppendMenuW@@$$J216YGHPAUHMENU__@@IIPB_W@Z) referenced in function "protected: virtual void __clrcall context_menu::Form1::OnHandleCreated(class System::EventArgs ^)" (?OnHandleCreated@Form1@context_menu@@$$FM$AAMXP$AAVEventArgs@System@@@Z)
1>context_menu.obj : error LNK2019: unresolved external symbol "extern "C" struct HMENU__ * __stdcall GetSystemMenu(struct HWND__ *,int)" (?GetSystemMenu@@$$J18YGPAUHMENU__@@PAUHWND__@@H@Z) referenced in function "protected: virtual void __clrcall context_menu::Form1::OnHandleCreated(class System::EventArgs ^)" (?OnHandleCreated@Form1@context_menu@@$$FM$AAMXP$AAVEventArgs@System@@@Z)

那么现在呢?

代码:

代码语言:javascript
复制
#pragma once
#include <Windows.h>
#include <string>

namespace context_menu {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Runtime::InteropServices;
    using std::string;

    /// <summary>
    /// Summary for Form1
    ///
    /// WARNING: If you change the name of this class, you will need to change the
    ///          'Resource File Name' property for the managed resource compiler tool
    ///          associated with all .resx files this class depends on.  Otherwise,
    ///          the designers will not be able to interact properly with localized
    ///          resources associated with this form.
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    // ID for the About item on the system menu
    private: static int SYSMENU_ABOUT_ID = 0x1;


    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->SuspendLayout();
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(284, 261);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);

        }
#pragma endregion

    protected: virtual System::Void OnHandleCreated( System::EventArgs^ e ) override {
                // Basic function call
                System::Windows::Forms::Form::OnHandleCreated( e );
                // Pointer to this
                HWND hWnd = static_cast<HWND>( this->Handle.ToPointer() );
                // Get a handle to a copy of this form's system (window) menu
                HMENU sysMenuHandle = GetSystemMenu( hWnd, false );
                // Add a separator
                AppendMenu( sysMenuHandle, MF_SEPARATOR, 0, L"" );
                // Add the About menu item
                AppendMenu( sysMenuHandle, MF_STRING, SYSMENU_ABOUT_ID, L"&About…\n" );
            }

    protected: virtual System::Void WndProc( Message % m ) override {
                // Basic function call
                System::Windows::Forms::Form::WndProc( m );
                // komunikat
                if( ( m.Msg == WM_SYSCOMMAND ) && ( (int)m.WParam == SYSMENU_ABOUT_ID ) )
                {
                    MessageBox::Show( "Custom About Dialog" );
                }
            }
    };
}
EN

回答 1

Stack Overflow用户

发布于 2019-04-16 03:44:48

你已经在C++中了,你不需要P/Invoke。只需使用#include <Windows.h>并直接调用函数即可。

代码语言:javascript
复制
[DllImport("user32.dll", CharSet = System::Runtime::InteropServices::CharSet::Auto, SetLastError = true)]
extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);
                                                                 ^^^^^^

在C#中,string是一个与C++/CLI不同的类。由于出现了一些东西,但它不正确,我认为字符串很可能没有正确传递。

如果您切换到直接调用C函数,则对字符串参数的类型检查将帮助您正确地传递该参数。

尽管如此,标准警告:虽然可以用C++/CLI编写应用程序的主体,甚至可以使用WinForms用C++/CLI编写图形用户界面,但不建议这样做。C++/CLI适用于互操作场景:当C#或其他.Net代码需要与非托管C++交互时,C++/CLI可以提供两者之间的转换。正因为如此,C++/CLI既有C++的所有复杂性,也有C#的所有复杂性,还有它自己的一些复杂性。对于初级开发,如果需要托管代码,建议将C#与WinForms或WPF一起使用;如果希望非托管,则建议将C++与MFC一起使用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55695856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档