【问题标题】:How to keep a Form always on top without stealing focus from the active Window?如何在不从活动窗口中窃取焦点的情况下保持表单始终位于顶部?
【发布时间】:2023-03-16 09:02:02
【问题描述】:

我的问题:我如何才能让我的表单始终位于顶部(我可以设置TopMost = true),而不会在与我的表单交互时从当前活动的窗口中窃取焦点。

查看图像以更好地理解我的问题:表单位于顶部,当我专注于表单之外的任何其他输入控件时,我可以将选定的表情符号发送给它。

1:当我单击表单中的表情符号按钮时,我希望在 FireFox 的输入框中发生的图像。

2:我的表单的图像:只要我单击表单中的按钮,焦点就会移回该表单。

【问题讨论】:

    标签: c++ winforms c++-cli


    【解决方案1】:
    1. 制作一个标准表单,设置它的FormBorderStyle = none。让它成为 TopMost(这个设置本身是另一个话题,我不打算在这里讨论它)。
    2. 覆盖CreateParams 以设置WS_EX_NOACTIVATE and WS_EX_TOOLWINDOW 扩展样式。这可以防止表单在其表面内生成鼠标事件时被激活(请参阅有关这些样式的文档)。
    3. 向其中添加一些不可选择的按钮控件(如下所示的 ButtonNoSel 控件)并将其Tag 属性设置为与这些按钮显示的表情符号图像对应的 Unicode 字符。李>
    4. 为所有按钮添加相同的 Click 处理程序。

    单击这些按钮时,只需使用SendKeys::Send()(又名SendInput())将选定的Unicode 字符发送到前台窗口,转换为字符串Tag 属性值。

    这就是它的工作原理(将表情符号设置为 FireFox 显示的网页):


    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Windows::Forms;
    using namespace System::Drawing;
    
    public ref class frmKeyBoard : public System::Windows::Forms::Form
    {
    public:
        frmKeyBoard(void) { InitializeComponent(); }
    
    // [...] Initialization...
    
    protected:
        property System::Windows::Forms::CreateParams^ CreateParams {
            virtual System::Windows::Forms::CreateParams^ get() override {
                auto cp = Form::CreateParams;
                cp->ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
                return cp;
            }
        }
    
    // Event handler for all the Buttons
    private:
        System::Void buttonNoSelAll_Click(System::Object^  sender, System::EventArgs^  e) {
            Control^ ctl = safe_cast<Control^>(sender);
            SendKeys::Send(ctl->Tag->ToString());
        }
    };
    

    将这个简单的自定义控件添加到项目中。
    此控件仅使用Control.SetStyle,设置ControlStyles::Selectable = false 以防止子控件在与之交互时成为ActiveControl,因为它不接收焦点。

    using namespace System;
    using namespace System::Windows::Forms;
    using namespace System::ComponentModel;
    
    namespace CustomControls {
        [ToolboxItem(true)]
        public ref class ButtonNoSel : public System::Windows::Forms::Button
        {
        public:
            ButtonNoSel(void) {
                this->InitializeComponent();
                this->SetStyle(ControlStyles::Selectable, false);
            }
    
        private:
            void InitializeComponent(void) {
                this->UseVisualStyleBackColor = true;
            }
    
        protected:
            // delete managed resources, if any
            ~ButtonNoSel() { this->!ButtonNoSel(); }
            // delete unmanaged resources, if any
            !ButtonNoSel() { }
        };
    }
    

    请注意,此表单必须在自己的线程上运行。
    如果您需要从另一个表单显示此表单,请使用Task.Run() 将其显示为对话窗口,调用ShowDialog()。这将启动消息循环。

    例如,来自另一个 Form 的 Button.Click 处理程序(此处名为 MainForm)。

    private: 
        void ShowKeyboard() {
            frmKeyBoard^ fk = gcnew frmKeyBoard();
            fk->ShowDialog();
            delete fk;
        }
    
    private: 
        System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
            Task::Run(gcnew Action(this, &MainForm::ShowKeyboard));
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多