Как перетащить кнопку в Visual C ++ - PullRequest
1 голос
/ 19 мая 2011

Привет ...

Я работаю в Visual C ++ в .NET Framework, и мне нужно иметь возможность перемещать кнопку во время выполнения так, чтобы я удерживал ее мышью, а затем оставлял ее в нужном месте, другими словами, перетащите кнопку.

Мне не нужно перетаскивать его в другой контейнер, но в том же контейнере, например, родительский элемент кнопки - panel1, я хочу переместить кнопку внутри panel1.

Важно отметить, что я хочу иметь возможность выполнять код во время перемещения кнопки, а не после этого, например, выводить местоположение кнопки после каждого ее изменения.

Надеюсь, это проясняет идею, есть ли способ достичь этого?

Заранее спасибо:)

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018
    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;
    }
    };

    }
0 голосов
/ 05 апреля 2014

Я предполагаю, что вы используете Managed C ++ / CLI или просто Visual C ++.

Для той части, в которой вам нужно запускать код одновременно, возможно, вам понадобится дополнительная нить, чтобы этот код работал в фоновом режиме. См. Документацию :: CreateThread.

И, как мне кажется, вам придется вручную обрабатывать перетаскивание кнопки, если она является членом CDialog. Даже код, который не позволяет кнопке выходить за пределы панели (кстати, что вы имеете в виду под «панелью»? Это групповое поле?). См. Документацию для

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

и не забудьте добавить эти строки в карту сообщений

ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...