2010-03-05 11 views
6

मैं एक कस्टम नियंत्रण का निर्माण किया है की खींच simulates, और मैं चाहता हूँ लोगों को क्लिक करें और मेरे नियंत्रण पर खींचें करने के लिए बस के रूप में यदि वे विंडो शीर्षक बार पर खींचकर थे अनुमति देने के लिए। इसे करने का बेहतरीन तरीका क्या है?नियंत्रण कि विंडो शीर्षक बार

अब तक मैं माउस नीचे का लाभ, ऊपर में असफल रहा है, और जब खिड़की से ले जाया जा करने की जरूरत है समझने के लिए घटनाओं के लिए कदम।

उत्तर

10

मेरे अन्य जवाब देने के लिए इसके अलावा, आप इस मैन्युअल रूप से इस तरह एक नियंत्रण में कर सकते हैं:

Point dragOffset; 

protected override void OnMouseDown(MouseEventArgs e) { 
    base.OnMouseDown(e); 
    if (e.Button == MouseButtons.Left) { 
     dragOffset = this.PointToScreen(e.Location); 
     var formLocation = FindForm().Location; 
     dragOffset.X -= formLocation.X; 
     dragOffset.Y -= formLocation.Y; 
    } 
} 

protected override void OnMouseMove(MouseEventArgs e) { 
    base.OnMouseMove(e); 

    if (e.Button == MouseButtons.Left) { 
     Point newLocation = this.PointToScreen(e.Location); 

     newLocation.X -= dragOffset.X; 
     newLocation.Y -= dragOffset.Y; 

     FindForm().Location = newLocation; 
    } 
} 

संपादित: परीक्षण किया गया और तय - यह अब वास्तव में काम करता है।

+0

कोड के लिए धन्यवाद! –

5

यह करने के लिए सबसे प्रभावी तरीका WM_NCHITTEST अधिसूचना को संभालने के लिए है।

प्रपत्र के WndProc विधि ओवरराइड और निम्न कोड जोड़ें:

if (m.Msg == 0x0084) {    //WM_NCHITTEST 
    var point = new Point((int)m.LParam); 
    if(someRect.Contains(PointToClient(point)) 
     m.Result = new IntPtr(2); //HT_CAPTION 
} 

हालांकि, मुझे नहीं लगता कि अगर उस बिंदु पर एक नियंत्रण है संदेश भेजा जाएगा है।

+0

मैं चिंतित हूं ... क्या आप विस्तृत कर सकते हैं? धरती पर यह कैसे किया जा रहा है? – echo

+0

@echo: यह विंडोज को बताता है कि फॉर्म का वह हिस्सा टाइटलबार है, जिसे खींचा जा सकता है। ध्यान दें कि इससे उस भाग को डबल-क्लिक करके फ़ॉर्म को अधिकतम करने की अनुमति भी मिल जाएगी। – SLaks

+0

हां, साफ चाल, मैंने इसे पहले कभी नहीं देखा है। मुझे क्या पता चल रहा था यह जानने के लिए मुझे एक मिनट लगा! – Aaronaught

3

आप फार्म का एक हिस्सा शीर्षक की तरह व्यवहार बनाना चाहते हैं, WM_NCHITTEST चाल कि SLaks दिया जाने का रास्ता है। लेकिन अगर आप एक बच्चे की खिड़की बनाना चाहते हैं तो फॉर्म खींचने में सक्षम हो और दूसरा तरीका है।

मूल रूप से यदि आप MOUSE_MOVE आदेश आईडी के साथ DefWindowProc करने के लिए एक WM_SYSCOMMAND संदेश भेजते हैं, फिर Windows खींचें मोड में जाना जाएगा। यह मूल रूप से कैप्शन कैसे करता है, लेकिन मध्य व्यक्ति को काटकर, हम इस ड्रैग को एक बच्चे की खिड़की से शुरू कर सकते हैं, और हमें अन्य सभी कैप्शन व्यवहार नहीं मिलते हैं।

public class form1 : Form 
{ 
    ... 

    [DllImport("user32.dll")] 
    static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, IntPtr lParam); 
    [DllImport("user32.dll")] 
    static extern bool ReleaseCapture(IntPtr hwnd); 

    const uint WM_SYSCOMMAND = 0x112; 
    const uint MOUSE_MOVE = 0xF012;  

    public void DragMe() 
    { 
    DefWindowProc(this.Handle, WM_SYSCOMMAND, (UIntPtr)MOUSE_MOVE, IntPtr.Zero); 
    } 


    private void button1_MouseDown(object sender, MouseEventArgs e) 
    { 
    Control ctl = sender as Control; 

    // when we get a buttondown message from a button control 
    // the button has capture, we need to release capture so 
    // or DragMe() won't work. 
    ReleaseCapture(ctl.Handle); 

    this.DragMe(); // put the form into mousedrag mode. 
    } 
+0

यह मेरे लिए काम करता था, लेकिन मुझे रिलीज कैप्चर को कोई तर्क नहीं था। [रिलीज कैप्चर] देखें (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646261 (v = vs.85) .aspx) – Erroneous

संबंधित मुद्दे