【问题标题】:How to drag-drop a button in visual c++如何在Visual C++中拖放一个按钮
【发布时间】:2011-05-19 00:18:15
【问题描述】:

您好……

我在 .net 框架中使用 Visual c++,我需要能够在运行时移动一个按钮,以便我用鼠标按住它,然后将它留在想要的位置,换句话说,拖放按钮。

我不需要将它拖放到另一个容器中,而是在同一个容器中,例如按钮的父级是panel1,我想将按钮移动到panel1中。

需要提及的重要一点是,我希望能够在按钮移动时而不是之后执行代码,例如,在每次更改按钮后输出按钮的位置。

希望这可以使想法清晰,有什么方法可以实现吗?

提前致谢:)

【问题讨论】:

  • 你的问题不清楚,难怪它还没有得到cmets也没有答案。 “在 .net 框架中使用 Visual C++”?这是否意味着您正在使用托管 C++/CLI?还是您只是在使用 Visual C++?

标签: .net visual-c++ drag-and-drop


【解决方案1】:

我假设您使用的是托管 C++/CLI,或者您只是使用 Visual C++。

对于您需要同时运行代码的部分,您可能需要一个额外的线程来让该代码在后台运行。请参阅 ::CreateThread 文档。

在我看来,如果它是 CDialog 的成员,您必须手动处理按钮拖动。甚至不允许按钮离开面板的代码(顺便说一句,“面板”是什么意思?它是一个组框吗?)。请参阅文档

  • CWnd::OnMouseMove
  • CWnd::OnLButtonDown
  • CWnd::OnLButtonUp

不要忘记将此行添加到您的消息映射中

ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()

【讨论】:

    【解决方案2】:
        namespace Project1 {
    
        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::Collections::Generic;
        using namespace System::IO;
        using namespace System::Text;
    
    
        /// <summary>
        /// Summary for MyForm
        /// </summary>
        public ref class MyForm : public System::Windows::Forms::Form
        {
        private:
            static int m_textBoxCounter = 1;
            static int m_newButtoncounter = 1;
            static int s_btn_x_cord = 3;
            static int s_btn_y_cord = 3;
            static int s_tbox_x_cord = 335;
            static int s_tbox_y_cord = 3;
            static int m_TabIndexer = 5;
            static int m_x_cord = 0;
            static int m_y_cord = 0;
            bool isDragging = false;
            static int oldX, oldY;
            static int top, left;
    
            Int32 indexOfItemUnderMouseToDrag;
            Int32 indexOfItemUnderMouseToDrop;
            System::Drawing::Rectangle dragBoxFromMouseDown;
            Point screenOffset;
            System::Windows::Forms::Cursor^ MyNoDropCursor;
            System::Windows::Forms::Cursor^ MyNormalCursor;
    
        public:
            MyForm(void)
            {
                InitializeComponent();
                //
                //TODO: Add the constructor code here
                //
            }
    
        protected:
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            ~MyForm()
            {
                if (components)
                {
                    delete components;
                }
            }
        private: System::Windows::Forms::SplitContainer^  splitContainer1;
        private: System::Windows::Forms::Label^ label1;
        private: System::Windows::Forms::Button^  button1;
        private: System::Windows::Forms::Button^  button2;
        private: System::Windows::Forms::SaveFileDialog^  saveFileDialog1;
    
        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)
            {
                System::ComponentModel::ComponentResourceManager^  resources = (gcnew 
        System::ComponentModel::ComponentResourceManager(MyForm::typeid));
                this->splitContainer1 = (gcnew System::Windows::Forms::SplitContainer());
                this->label1 = (gcnew System::Windows::Forms::Label());
                this->button1 = (gcnew System::Windows::Forms::Button());
                this->button2 = (gcnew System::Windows::Forms::Button());
                this->saveFileDialog1 = (gcnew System::Windows::Forms::SaveFileDialog());
                (cli::safe_cast<System::ComponentModel::ISupportInitialize^> 
       (this>splitContainer1))->BeginInit();
                this->splitContainer1->Panel1->SuspendLayout();
                this->splitContainer1->SuspendLayout();
                this->SuspendLayout();
                // 
                // splitContainer1
                // 
                this->splitContainer1->IsSplitterFixed = true;
                this->splitContainer1->Location = System::Drawing::Point(11, 11);
                this->splitContainer1->Margin = System::Windows::Forms::Padding(2);
                this->splitContainer1->Name = L"splitContainer1";
                // 
                // splitContainer1.Panel1
                // 
                this->splitContainer1->Panel1->BackColor = System::Drawing::Color::White;
                this->splitContainer1->Panel1->Controls->Add(this->label1);
                this->splitContainer1->Panel1->Controls->Add(this->button1);
                this->splitContainer1->Panel1->Controls->Add(this->button2);
                // 
                // splitContainer1.Panel2
                // 
                this->splitContainer1->Panel2->AllowDrop = true;
                this->splitContainer1->Panel2->AutoScroll = true;
                this->splitContainer1->Panel2->BackColor = 
        System::Drawing::Color::Transparent;
                this->splitContainer1->Panel2->Padding = 
        System::Windows::Forms::Padding(2,     1, 2, 1);
                this->splitContainer1->Panel2->DragDrop += 
        gcnew System::Windows::Forms::DragEventHandler(this, &MyForm::Panel2_DragDrop);
                this->splitContainer1->Panel2->DragEnter += 
        gcnew System::Windows::Forms::DragEventHandler(this, &MyForm::Panel2_DragEnter);
                this->splitContainer1->Panel2->DragOver += 
        gcnew System::Windows::Forms::DragEventHandler(this, &MyForm::Panel2_DragOver);
                this->splitContainer1->Panel2->DragLeave += 
        gcnew System::EventHandler(this, &MyForm::Panel2_DragLeave);
                this->splitContainer1->Panel2->MouseUp += 
        gcnew System::Windows::Forms::MouseEventHandler(this, 
        &MyForm::splitContainer1_Panel2_MouseUP);
                this->splitContainer1->Size = System::Drawing::Size(634, 443);
                this->splitContainer1->SplitterDistance = 129;
                this->splitContainer1->SplitterWidth = 3;
                this->splitContainer1->TabIndex = 0;
                // 
                // label1
                // 
                this->label1->Location = System::Drawing::Point(3, 410);
                this->label1->Name = L"label1";
                this->label1->Size = System::Drawing::Size(292, 23);
                this->label1->TabIndex = 4;
                // 
                // button1
                // 
                this->button1->AutoEllipsis = true;
                this->button1->Cursor = System::Windows::Forms::Cursors::Default;
                this->button1->DialogResult = System::Windows::Forms::DialogResult::Cancel;
                this->button1->Location = System::Drawing::Point(17, 110);
                this->button1->Margin = System::Windows::Forms::Padding(2);
                this->button1->Name = L"button1";
                this->button1->Size = System::Drawing::Size(98, 19);
                this->button1->TabIndex = 0;
                this->button1->Text = L"Add Button";
                this->button1->UseVisualStyleBackColor = true;
                this->button1->DragEnter += 
        gcnew System::Windows::Forms::DragEventHandler(this, &MyForm::button_DragEnter);
                this->button1->MouseDown += 
        gcnew System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseDown);
                this->button1->MouseMove += gcnew 
        System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseMove);
                this->button1->MouseUp += 
        gcnew System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseUp);
                // 
                // button2
                // 
                this->button2->AutoEllipsis = true;
                this->button2->Cursor = System::Windows::Forms::Cursors::Default;
                this->button2->Location = System::Drawing::Point(17, 296);
                this->button2->Margin = System::Windows::Forms::Padding(2);
                this->button2->Name = L"button2";
                this->button2->Size = System::Drawing::Size(98, 19);
                this->button2->TabIndex = 1;
                this->button2->Text = L"Add TextBox";
                this->button2->UseVisualStyleBackColor = true;
                this->button2->DragEnter += gcnew 
        System::Windows::Forms::DragEventHandler(this, &MyForm::button_DragEnter);
                this->button2->MouseDown += gcnew 
        System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseDown);
                this->button2->MouseMove += gcnew 
        System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseMove);
                this->button2->MouseUp += gcnew 
        System::Windows::Forms::MouseEventHandler(this, &MyForm::button_MouseUp);
                // 
                // MyForm
                // 
                this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
                this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                this->AutoScroll = true;
                this->AutoSize = true;
                this->AutoSizeMode = System::Windows::Forms::AutoSizeMode::GrowAndShrink;
                this->BackColor = System::Drawing::Color::White;
                this->ClientSize = System::Drawing::Size(656, 463);
                this->Controls->Add(this->splitContainer1);
                this->ForeColor = System::Drawing::Color::Black;
                this->Icon = (cli::safe_cast<System::Drawing::
        Icon^>(resources->GetObject(L"$this.Icon")));
                this->Margin = System::Windows::Forms::Padding(2);
                this->MaximizeBox = false;
                this->MinimizeBox = false;
                this->Name = L"MyForm";
                this->StartPosition = 
        System::Windows::Forms::FormStartPosition::CenterScreen;
                this->Text = L"Run-time Control Manipulation";
                this->Load += gcnew System::EventHandler(this, &MyForm::MyForm_Load);
                this->splitContainer1->Panel1->ResumeLayout(false);
                (cli::safe_cast<System::ComponentModel::
        ISupportInitialize^>(this->splitContainer1))->EndInit();
                this->splitContainer1->ResumeLayout(false);
                this->ResumeLayout(false);
    
            }
        #pragma endregion
    
        private: System::Void button_MouseDown(System::Object^  /*sender*/, 
        System::Windows::Forms::MouseEventArgs^  e)
        {
            isDragging = true;
            oldX = e->X;
            oldY = e->Y;
    
            if ((e->Button == System::Windows::Forms::MouseButtons::Left)
                ||
                (e->Button == System::Windows::Forms::MouseButtons::Right))
            {
                System::Drawing::Size dragSize = SystemInformation::DragSize;
                dragBoxFromMouseDown = System::Drawing::Rectangle(Point(e->X - 
        (dragSize.Width / 2), e->Y - (dragSize.Height / 2)), dragSize);
            }
            else
            {
                this->button1->BackColor = System::Drawing::Color::Red;
            }
        }
    
        private: System::Void button_MouseMove(Object^ sender, 
        System::Windows::Forms::MouseEventArgs^ e)
        {
            if (isDragging)
            {
                //top = (e->Y - oldY); //((Button^)sender)->Top + (e->Y - oldY);
                //left = (e->X - oldX); //((Button^)sender)->Left + (e->X - oldX);
    
                if ((e->Button & System::Windows::Forms::MouseButtons::Left) == 
        System::Windows::Forms::MouseButtons::Left)
                {
                    // If the mouse moves outside the rectangle, start the drag.
                    if (dragBoxFromMouseDown != Rectangle::Empty && 
        dragBoxFromMouseDown.Contains(e->X, e->Y))
                    {
                        // The screenOffset is used to account for any desktop bands
                        // that may be at the top or left side of the screen when
                        // determining when to cancel the drag drop operation.
                        screenOffset = SystemInformation::WorkingArea.Location;
    
                        // Proceed with the drag-and-drop operation.
                        DragDropEffects dropEffect = 
        ((Button^)sender)->DoDragDrop(((Button^)sender)->Text, DragDropEffects::Copy);
    
                        // If the drag operation was a move then capture the location of the 
        mouse pointer.
                            m_x_cord = e->X;
                            m_y_cord = e->Y;
                    }
                }
            }
        }
    
        private: System::Void button_MouseUp(Object^ /*sender*/, 
        System::Windows::Forms::MouseEventArgs^ /*e*/)
        {
            // Reset the drag rectangle when the mouse button is raised.
            dragBoxFromMouseDown = Rectangle::Empty;
    
            isDragging = false;
    
            this->label1->Text = "Ready for Drag-Drop";
    
            this->button1->BackColor = System::Drawing::Color::WhiteSmoke;
            this->button1->AllowDrop = false;
            this->button2->BackColor = System::Drawing::Color::WhiteSmoke;
            this->button2->AllowDrop = false;
        }
    
        private: System::Void button_GiveFeedback(Object^ /*sender*/, 
        System::Windows::Forms::GiveFeedbackEventArgs^ e)
        {
            // Use custom cursors if the check box is checked.
            if (isDragging)
            {
                // Sets the custom cursor based upon the effect.
                e->UseDefaultCursors = false;
                if ((e->Effect == DragDropEffects::Move) 
        || (e->Effect == DragDropEffects::Copy))
                    System::Windows::Forms::Cursor::Current = MyNormalCursor;
                else
                    System::Windows::Forms::Cursor::Current = MyNoDropCursor;
            }
        }
    
        private: System::Void button_QueryContinueDrag(Object^ sender, 
        System::Windows::Forms::QueryContinueDragEventArgs^ e)
        {
            // Cancel the drag if the mouse moves off the form.
            Button^ lb = dynamic_cast<Button^>(sender);
            if (lb != nullptr)
            {
                Form^ f = lb->FindForm();
    
                // Cancel the drag if the mouse moves off the form. The screenOffset takes 
        into 
                // account any desktop bands that may be at the top or left side of the 
        screen.
                if (((Control::MousePosition.X - screenOffset.X) < f->DesktopBounds.Left) 
        || ((Control::MousePosition.X - screenOffset.X) > f->DesktopBounds.Right) 
        || ((Control::MousePosition.Y - screenOffset.Y) < f->DesktopBounds.Top)
        || ((Control::MousePosition.Y - screenOffset.Y) > f->DesktopBounds.Bottom))
                {
                    e->Action = DragAction::Cancel;
                }
            }
        }
    
        private: System::Void button_DragEnter(System::Object^  /*sender*/, 
        System::Windows::Forms::DragEventArgs^  e)
        {
            e->Effect = DragDropEffects::Copy;
        }
    
        private: System::Void tableLayoutPanel1_Paint(System::Object^  sender, 
        System::Windows::Forms::PaintEventArgs^  e)
        {
        }
    
        private: System::Void Panel2_DragLeave(System::Object^  /*sender*/, 
        System::EventArgs^  /*e*/)
        {
            // Reset the label text.
            this->label1->Text = "";
        }
    
        private: System::Void Panel2_DragDrop(System::Object^ /*sender*/, 
        System::Windows::Forms::DragEventArgs^  e)
        {
            // Reset the label text.
            this->label1->Text = "Ready for Drag-Drop";
    
            // Ensure that the dragged item is contained in the data.
            if (e->Data->GetDataPresent(System::String::typeid))
            {
                Object^ item =
        dynamic_cast<Object^>(e->Data->GetData(System::String::typeid));
                // Determine whether data exists in the drop data. If not, then
                // the drop effect reflects that the drop cannot occur.
                if ((e->AllowedEffect == DragDropEffects::Copy) || (e->AllowedEffect == 
        DragDropEffects::Move))
                {
                    if (item->ToString()->Contains("Add Button"))
                    {
                        this->label1->Text = "New Button dropped";
                        Button^ newBtn = gcnew Button();
                        newBtn->Left = left;
                        newBtn->Top =  top;
                        newBtn->Name = L"newButton" + m_newButtoncounter;
                        newBtn->TabIndex = m_TabIndexer;
                        newBtn->Text = L"New Button";
                        m_newButtoncounter++;
                        m_TabIndexer++;
                        this->splitContainer1->Panel2->Controls->Add(newBtn);
                        this->button1->BackColor = System::Drawing::Color::GhostWhite;
                    }
                    else
                        if (item->ToString()->Contains("Add TextBox"))
                        {
                            this->label1->Text = "New textBox dropped";
                            TextBox^ newtxtbox = gcnew TextBox();
                            newtxtbox->Left = left;
                            newtxtbox->Top = top;
                            newtxtbox->Name = L"newButton" + m_textBoxCounter;
                            newtxtbox->TabIndex = m_TabIndexer;
                            newtxtbox->Text = L"New textBox";
                            m_textBoxCounter++;
                            m_TabIndexer++;
                            this->splitContainer1->Panel2->Controls->Add(newtxtbox);
                            this->button1->BackColor = 
    System::Drawing::Color::GhostWhite;
                        }
                    delete item;
                    return;
                }
            }
        }
    
        private: System::Void Panel2_DragEnter(System::Object^  sender, 
        System::Windows::Forms::DragEventArgs^  /*e*/)
        {
            Button^ lb = dynamic_cast<Button^>(sender);
    
            // Reset the label text.
            this->label1->Text = "Ready for Drop";
    
            if (lb != nullptr)
            {
                // Determine whether data exists in the drop data. If not, then
                // the drop effect reflects that the drop cannot occur.
    
                if (((Button^)sender)->Text == "Add TextBox")
                {
                    this->label1->Text = "TextBox can be dropped";
                    this->button1->BackColor = System::Drawing::Color::AntiqueWhite;
                }
                else
                    if (((Button^)sender)->Text == "Add Button")
                    {
                        this->label1->Text = "Button can be dropped";
                        this->button2->BackColor = System::Drawing::Color::AntiqueWhite;
                    }
                delete lb;
                return;
            }
        }
    
        private: System::Void Panel2_DragOver(System::Object^  /*sender*/, 
        System::Windows::Forms::DragEventArgs^  e)
        {
            //Point^ location = this->button1->PointToScreen;
    
            Object^ item = 
    dynamic_cast<Object^>(e->Data->GetData(System::String::typeid));
    
            // Determine whether string data exists in the drop data. If not, then
                // the drop effect reflects that the drop cannot occur.
            if (!e->Data->GetDataPresent(System::String::typeid))
            {
                e->Effect = DragDropEffects::None;
                this->label1->Text = "No Dropped Control.";
                return;
            }
    
            // Set the effect based upon the KeyState.
            if ((e->KeyState & (8 + 32)) == (8 + 32) && ((e->AllowedEffect & 
        DragDropEffects::Link) == DragDropEffects::Link))
            {
                // KeyState 8 + 32 = CTL + ALT
                // Link drag-and-drop effect.
                e->Effect = DragDropEffects::Link;
            }
            else
                if ((e->KeyState & 32) == 32 && 
        ((e->AllowedEffect & DragDropEffects::Link) == DragDropEffects::Link))
                {
                    // ALT KeyState for link.
                    e->Effect = DragDropEffects::Link;
                }
                else
                    if ((e->KeyState & 4) == 4 && 
        ((e->AllowedEffect & DragDropEffects::Move) == DragDropEffects::Move))
                    {
                        // SHIFT KeyState for move.
                        e->Effect = DragDropEffects::Move;
                    }
                    else
                        if ((e->KeyState & 8) == 8 && 
        ((e->AllowedEffect & DragDropEffects::Copy) == DragDropEffects::Copy))
                        {
                            // CTL KeyState for copy.
                            e->Effect = DragDropEffects::Copy;
                        }
                        else
                            if ((e->AllowedEffect & DragDropEffects::Move) == 
        DragDropEffects::Move)
                            {
                                // By default, the drop action should be move, if allowed.
                                e->Effect = DragDropEffects::Move;
                            }
                            else
                                e->Effect = DragDropEffects::None;
    
            if ((item->ToString()->Contains("Add TextBox")) 
        || (item->ToString()->Contains("Add Button")))
            {
                e->Effect = DragDropEffects::Copy;
                this->label1->Text = item->ToString()->Replace("Add ","") +" can be 
     Dropped";
            }
        }
    
        private: System::Void splitContainer1_Panel2_MouseUP(System::Object^  /*sender*/, 
        System::Windows::Forms::MouseEventArgs^  /*e*/)
        {
            this->button1->BackColor = System::Drawing::Color::Aqua;
            this->button2->BackColor = System::Drawing::Color::Aqua;
        }
    
        private: System::Void MyForm_Load(System::Object^  sender, System::EventArgs^  e)
        {
            this->Size = System::Drawing::Size(15, 265);
            this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D;
        }
        };
    
        }
    

    【讨论】:

    • 欢迎来到 StackOverflow。虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 How to Answer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多