How to drag-drop a button in visual c++
Greetings...
I'm working in visual c++ in the .net framework, and I need to be able to move a button in the runtime such that I hold it with the mouse and then leave it in the wanted place, in other words, drag and drop the button.
I don't need to drag and drop it in another container, but i开发者_开发技巧n the same container, for example the parent of the button is panel1, I want to move the button inside panel1.
Something important to mention is that I want to be able to perform code while the button is being moved and not after that, for example, outputting the location of the button after every single change on it.
Hopefully that makes the idea clear, is there any way to achieve that?
Thanks in advance :)
I will assume you are using Managed C++/CLI or you simply Visual C++.
For the part that you need to run code at the same time, maybe you will need an extra thread for that code to run in background. See the ::CreateThread documentation.
And seems to me you have to do manually the processing of the button dragging if it is a member of a CDialog. Even the code to not allow the button go ouside the panel (by the way, what you mean with "panel"? Is it a groupbox?) . See documentation for
- CWnd::OnMouseMove
- CWnd::OnLButtonDown
- CWnd::OnLButtonUp
and do not forget to add this lines to your message map
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
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;
}
};
}
精彩评论