ডাব্লুপিএফ উইন্ডোটিকে টেনে নিয়ে যেতে সক্ষম করুন, যাই হোক না কেন উপাদানটি ক্লিক করা হয়


111

আমার প্রশ্ন ভাঁজ 2, এবং আমি আশা করছি উভয় দ্বারা উপলব্ধ করা আরো সহজ সমাধান আছে WPF বদলে WinForms থেকে মান সমাধান (যা ক্রিস্টোফ Geers প্রদান, আগে আমি এই শোধন করেছি)।

প্রথমত, মাউস ক্লিক + ড্র্যাগ ইভেন্টগুলি ক্যাপচার এবং প্রক্রিয়াজাত না করে উইন্ডোটিকে টেনে আনেযোগ্য করার কোনও উপায় আছে? আমার অর্থ উইন্ডোটি শিরোনাম বার দ্বারা টেনে আনতে সক্ষম, তবে যদি আমি একটি উইন্ডো না রাখি এবং এটি এখনও টেনে আনতে সক্ষম হতে চাই তবে শিরোনাম দণ্ডটি টানাটাকে যেভাবে হ্যান্ডল করে তাতে ইভেন্টগুলি পুনরায় নির্দেশ করার কোনও উপায় আছে কি? ?

দ্বিতীয়ত, উইন্ডোতে সমস্ত উপাদানগুলিতে ইভেন্ট হ্যান্ডলারটি প্রয়োগ করার কোনও উপায় আছে কি? হিসাবে, উইন্ডোটিকে ড্রাগযোগ্য করে তুলুন যা ব্যবহারকারীরা কোন উপাদান ক্লিক করেন + টেনে আনেন। স্পষ্টতই হ্যান্ডলারটি প্রতিটি একক উপাদানে ম্যানুয়ালি যোগ করা ছাড়া। শুধু একবার কোথাও না?

উত্তর:


284

অবশ্যই, আপনার নিম্নলিখিত MouseDownইভেন্টটি প্রয়োগ করুনWindow

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ChangedButton == MouseButton.Left)
        this.DragMove();
}

এটি ব্যবহারকারীরা যখন কোনও নিয়ন্ত্রণে ক্লিক / টেনে আনলে উইন্ডোটি টেনে আনতে দেয়, মাউসডাউন ইভেন্ট খায় এমন নিয়ন্ত্রণের জন্য EXCEPT (e.Handled = true )

আপনি তার PreviewMouseDownপরিবর্তে ব্যবহার করতে পারেন MouseDown, তবে ড্রাগন ইভেন্টটি ইভেন্টটি খায় Click, তাই আপনার উইন্ডোটি বাম-মাউস ক্লিক ইভেন্টগুলিতে প্রতিক্রিয়া বন্ধ করে। আপনি যদি সত্যিই কোনও নিয়ন্ত্রণ থেকে ফর্মটি ক্লিক করতে এবং টেনে আনতে সক্ষম হতে চান, আপনি সম্ভবত এটি ব্যবহার করতে পারেন PreviewMouseDown, টেনে টানুন শুরু করতে টাইমার শুরু করতে এবং MouseUpএক্স মিলিসেকেন্ডের মধ্যে ইভেন্টটি আগুন লাগলে অপারেশনটি বাতিল করতে পারেন ।


+1 টি। উইন্ডো ম্যানেজারটিকে অবস্থানটি মনে করে এবং উইন্ডোটি সরানোর পরিবর্তে এটিকে নকল করার পরিবর্তে চালনাটি পরিচালনা করা আরও ভাল। (পরবর্তী পদ্ধতিটি যে কোনও উপায়ে ভুল পথে যাওয়ার প্রবণতাও রয়েছে)
জো

কেবলমাত্র MouseLeftButtonDown.cs এ যাচাই না করে ইভেন্টটি সেট করবেন না কেন ?

1
@ ড্রোইন আপনি সম্ভবত এর পরিবর্তে সেই ইভেন্টটি ব্যবহার করতে পারেন তবে নিশ্চিত হয়ে নিন যে আপনি প্রথমে এটি পরীক্ষা MouseLeftButtonDownকরেছেন যেহেতু বুবলিং রাউটিং কৌশল রয়েছে তখন সরাসরি রাউটিং কৌশল MouseDownরয়েছে। এর মন্তব্য বিভাগটি দেখুন MouseLeftButtonDown জন্য দুটিই MSDN পৃষ্ঠা আরও তথ্যের জন্য, এবং কিছু অতিরিক্ত জিনিস জন্য আপনি ব্যবহার করে থাকতে যাচ্ছেন যদি সচেতন হতে হবে MouseLeftButtonDownউপর MouseDown
রাহেল

@ রাচেল হ্যাঁ আমি এটি ব্যবহার করছি এবং এটি কার্যকর হয় তবে ব্যাখ্যাটির জন্য ধন্যবাদ!

2
@ রাহুল একটি ইউজারকন্ট্রোলকে টেনে আনাই অনেক বেশি শক্ত ... আপনার এটিকে ক্যানভাসের মতো প্যারেন্ট প্যানেলে স্থাপন করতে হবে এবং ব্যবহারকারীর মাউসটি সরানোর সাথে সাথে ম্যানুয়ালি এক্স / ওয়াই (বা ক্যানভাস.টপ এবং ক্যানভাস। লেফট) বৈশিষ্ট্য নির্ধারণ করতে হবে। আমি শেষবার মাউস ইভেন্টগুলি ব্যবহার করেছিলাম, সুতরাং অনমাউসডাউন ক্যাপচার অবস্থান এবং নিবন্ধন সরানো ইভেন্ট, অনমোসমোভ পরিবর্তন এক্স / ওয়াই, এবং অনমাউসআপ সরানো ইভেন্ট সরান। এটি এর প্রাথমিক ধারণা :)
রাচেল

9

যদি ডাব্লুপিএফ ফর্মটি ড্র্যাগেবল হতে পারে তবে যেখানেই ক্লিক করা হয়েছিল সহজ কাজ যেখানে উইন্ডোজ অনলোড ইভেন্ট বা গ্রিড লোড ইভেন্টের উপর ড্র্যাগমোভ () পদ্ধতিটি ট্রিগার করতে একটি প্রতিনিধি ব্যবহার করা হয়

private void Grid_Loaded(object sender, RoutedEventArgs 
{
      this.MouseDown += delegate{DragMove();};
}

2
আমি এটি কনস্ট্রাক্টরের সাথে যুক্ত করেছি। একটি কবজ কাজ করে।
জো জনস্টন 16

1
আপনি যদি ফর্মের যে কোনও জায়গায় ডান-ক্লিক করেন তবে এটি একটি ব্যতিক্রম ছুঁড়ে ফেলবে, কারণ DragMoveপ্রাথমিক মাউস বোতামটি নীচে থাকলে কেবল তখনই কল করা যেতে পারে।
স্টেপ্পান বকরাক

4

কখনও কখনও, আমাদের অ্যাক্সেস নেই Window, উদাহরণস্বরূপ যদি আমরা ব্যবহার করি তবে DevExpressযা পাওয়া যায় তা হ'ল একটি UIElement

পদক্ষেপ 1: সংযুক্ত সম্পত্তি যুক্ত করুন

সমাধানটি হ'ল:

  1. MouseMoveঘটনাগুলিতে আবদ্ধ ;
  2. আমরা প্রথম পিতামাতাকে না পাওয়া পর্যন্ত ভিজ্যুয়াল ট্রি অনুসন্ধান করুন Window;
  3. .DragMove()আমাদের সদ্য আবিষ্কৃতকে কল করুন Window

কোড:

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace DXApplication1.AttachedProperty
{
    public class EnableDragHelper
    {
        public static readonly DependencyProperty EnableDragProperty = DependencyProperty.RegisterAttached(
            "EnableDrag",
            typeof (bool),
            typeof (EnableDragHelper),
            new PropertyMetadata(default(bool), OnLoaded));

        private static void OnLoaded(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var uiElement = dependencyObject as UIElement;
            if (uiElement == null || (dependencyPropertyChangedEventArgs.NewValue is bool) == false)
            {
                return;
            }
            if ((bool)dependencyPropertyChangedEventArgs.NewValue  == true)
            {
                uiElement.MouseMove += UIElementOnMouseMove;
            }
            else
            {
                uiElement.MouseMove -= UIElementOnMouseMove;
            }

        }

        private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            var uiElement = sender as UIElement;
            if (uiElement != null)
            {
                if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
                {
                    DependencyObject parent = uiElement;
                    int avoidInfiniteLoop = 0;
                    // Search up the visual tree to find the first parent window.
                    while ((parent is Window) == false)
                    {
                        parent = VisualTreeHelper.GetParent(parent);
                        avoidInfiniteLoop++;
                        if (avoidInfiniteLoop == 1000)
                        {
                            // Something is wrong - we could not find the parent window.
                            return;
                        }
                    }
                    var window = parent as Window;
                    window.DragMove();
                }
            }
        }

        public static void SetEnableDrag(DependencyObject element, bool value)
        {
            element.SetValue(EnableDragProperty, value);
        }

        public static bool GetEnableDrag(DependencyObject element)
        {
            return (bool)element.GetValue(EnableDragProperty);
        }
    }
}

পদক্ষেপ 2: উইন্ডোটি টেনে আনতে যেকোন উপাদানকে সংযুক্ত সম্পত্তি যুক্ত করুন

আমরা যদি এই সংযুক্ত সম্পত্তিটিকে যুক্ত করি তবে ব্যবহারকারী কোনও নির্দিষ্ট উপাদানটিতে ক্লিক করে পুরো উইন্ডোটি টেনে আনতে পারে:

<Border local:EnableDragHelper.EnableDrag="True">
    <TextBlock Text="Click me to drag this entire window"/>
</Border>

পরিশিষ্ট এ: Advancedচ্ছিক উন্নত উদাহরণ

থেকে এই উদাহরণে DevExpress , আমরা আমাদের নিজস্ব ধূসর আয়তক্ষেত্র সঙ্গে একটি ডকিং উইন্ডোর শিরোনাম দণ্ড প্রতিস্থাপন, তারপর নিশ্চিত করুন যে, তাহলে ব্যবহারকারী ক্লিক এবং মাদকের ধূসর rectagle বললেন, জানালা স্বাভাবিকভাবে টেনে হবে:

<dx:DXWindow x:Class="DXApplication1.MainWindow" Title="MainWindow" Height="464" Width="765" 
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking" 
    xmlns:local="clr-namespace:DXApplication1.AttachedProperty"
    xmlns:dxdove="http://schemas.devexpress.com/winfx/2008/xaml/docking/visualelements"
    xmlns:themeKeys="http://schemas.devexpress.com/winfx/2008/xaml/docking/themekeys">

    <dxdo:DockLayoutManager FloatingMode="Desktop">
        <dxdo:DockLayoutManager.FloatGroups>
            <dxdo:FloatGroup FloatLocation="0, 0" FloatSize="179,204" MaxHeight="300" MaxWidth="400" 
                             local:TopmostFloatingGroupHelper.IsTopmostFloatingGroup="True"                             
                             >
                <dxdo:LayoutPanel ShowBorder="True" ShowMaximizeButton="False" ShowCaption="False" ShowCaptionImage="True" 
                                  ShowControlBox="True" ShowExpandButton="True" ShowInDocumentSelector="True" Caption="TradePad General" 
                                  AllowDock="False" AllowHide="False" AllowDrag="True" AllowClose="False"
                                  >
                    <Grid Margin="0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Border Grid.Row="0" MinHeight="15" Background="#FF515151" Margin="0 0 0 0"
                                                                  local:EnableDragHelper.EnableDrag="True">
                            <TextBlock Margin="4" Text="General" FontWeight="Bold"/>
                        </Border>
                        <TextBlock Margin="5" Grid.Row="1" Text="Hello, world!" />
                    </Grid>
                </dxdo:LayoutPanel>
            </dxdo:FloatGroup>
        </dxdo:DockLayoutManager.FloatGroups>
    </dxdo:DockLayoutManager>
</dx:DXWindow>

দাবি পরিত্যাগী: আমি না সঙ্গে সম্বন্ধযুক্ত DevExpress । এই কৌশলটি স্ট্যান্ডার্ড ডাব্লুপিএফ বা টেলিরিক (অন্য সূক্ষ্ম ডাব্লুপিএফ গ্রন্থাগার সরবরাহকারী) সহ যে কোনও ব্যবহারকারীর উপাদানগুলির সাথে কাজ করবে ।


1
আমি ঠিক তাই চেয়েছিলাম আইএমএইচও এর পিছনে সমস্ত ডাব্লুপিএফ কোড সংযুক্ত আচরণ হিসাবে লেখা উচিত।
fjch1997

3
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
    this.DragMove();
}

কিছু ক্ষেত্রে একটি ব্যতিক্রম ছোঁড়াচ্ছে (যেমন উইন্ডোতে যদি আপনার কাছে একটি ক্লিকযোগ্য চিত্রও থাকে যা ক্লিক করার সময় কোনও বার্তা বাক্স খোলে।

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
            this.DragMove();
}

সুতরাং আপনি নিশ্চিত যে সেই মুহুর্তে বাম বোতামটি টিপছে।


আমি ইভেন্ট আরগগুলির সাথে যুক্ত বোতামটি বিশেষভাবে ব্যবহার করার e.LeftButtonপরিবর্তে ব্যবহার করছি Mouse.LeftButton, যদিও এটি সম্ভবত কোনও বিষয় নয়।
ফ্লস'জেন

2

কেবল শিরোনাম বার নয়, ফর্মের যে কোনও জায়গায় ক্লিক করে কোনও ফর্ম টেনে আনতে এবং নামানো সম্ভব। আপনার সীমান্তহীন ফর্ম থাকলে এটি কার্যকর।

কোডপ্রজেক্টের এই নিবন্ধটি এটি বাস্তবায়নের জন্য একটি সম্ভাব্য সমাধান দেখায়:

http://www.codeproject.com/KB/cs/DraggableForm.aspx

মূলত ফর্ম টাইপের একটি বংশধর তৈরি করা হয় যেখানে মাউস ডাউন, আপ এবং মুভ ইভেন্টগুলি পরিচালনা করা হয়।

  • মাউস ডাউন: অবস্থান মনে রাখবেন remember
  • মাউস সরানো: নতুন অবস্থান সঞ্চয় করুন
  • মাউস আপ: অবস্থানের ফর্মটি নতুন স্থানে

এবং এখানে একটি ভিডিও টিউটোরিয়ালে বর্ণিত একটি অনুরূপ সমাধান:

http://www.youtube.com/watch?v=tJlY9aX73Vs

যখন ব্যবহারকারী কোনও ফর্মটিতে কোনও নিয়ন্ত্রণ ক্লিক করে তখন আমি ফর্মটি টেনে আনতে দেব না। ব্যবহারকারীরা যখন বিভিন্ন নিয়ন্ত্রণে ক্লিক করেন তখন বিভিন্ন ফলাফলকে ছদ্মবেশে ফেলে। যখন আমার ফর্মটি হঠাৎ চলতে শুরু করে কারণ আমি একটি তালিকাবক্স, বোতাম, লেবেল ... ইত্যাদি ক্লিক করেছি। বিভ্রান্তিকর হবে।


নিশ্চিত যে এটি কোনও নিয়ন্ত্রণে ক্লিক করে সরবে না, তবে আপনি ক্লিক করে এবং টেনে নিয়ে গেলে, আপনি কী ফর্মটি সরানোর প্রত্যাশা করবেন না? আমি বলতে চাইছি আপনি উদাহরণস্বরূপ কোনও বোতাম বা একটি তালিকা বাক্স সরিয়ে নেবেন না, উদাহরণস্বরূপ আপনি ক্লিক করে + এটিকে টেনে আনেন, ফর্মটির গতি একটি প্রাকৃতিক প্রত্যাশা যদি আপনি ফর্মের একটি বোতামটি ক্লিক করে টেনে আনার চেষ্টা করেন, তবে আমি মনে করি।
অ্যালেক্স কে

অনুমান করুন, এটি কেবল ব্যক্তিগত স্বাদ। যাইহোক .... নিয়ন্ত্রণগুলির একই মাউস ইভেন্টগুলি পরিচালনা করতে হবে। এই ইভেন্টগুলি বুদবুদ না হওয়ার কারণে আপনাকে তাদের পিতামাতার ফর্মটি অবহিত করতে হবে।
ক্রিস্টোফ গিয়ার্স

এছাড়াও, আমি এটির উইনফোর্ডস সমাধান সম্পর্কে সচেতন থাকাকালীন, আমি ডাব্লুপিএফ-তে আরও সহজতর একটি উপায়ের জন্য প্রত্যাশা করছিলাম, আমি অনুমান করি যে এই প্রশ্নটিতে আমার আরও পরিষ্কার করা উচিত (এখনই এটি কেবল একটি ট্যাগ)।
অ্যালেক্স কে

দুঃখিত আমার খারাপ. ডাব্লুপিএফ ট্যাগ খেয়াল করেনি। মূল প্রশ্নের মধ্যে উল্লেখ করা হয়নি। আমি কেবল ডিফল্টভাবে উইনফর্মগুলি ধরে নিয়েছি, ট্যাগটি দেখেছি।
ক্রিস্টোফ গিয়ার্স

2

@ Fjch1997 দ্বারা ইতিমধ্যে উল্লিখিত হিসাবে এটি আচরণ বাস্তবায়ন করা সুবিধাজনক। এটি এখানে, মূল যুক্তিটি @ লুই.এফির উত্তরের মতো :

public class DragMoveBehavior : Behavior<Window>
{
    protected override void OnAttached()
    {
        AssociatedObject.MouseMove += AssociatedObject_MouseMove;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
    }

    private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed && sender is Window window)
        {
            // In maximum window state case, window will return normal state and
            // continue moving follow cursor
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;

                // 3 or any where you want to set window location after
                // return from maximum state
                Application.Current.MainWindow.Top = 3;
            }

            window.DragMove();
        }
    }
}

ব্যবহার:

<Window ...
        xmlns:h="clr-namespace:A.Namespace.Of.DragMoveBehavior"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Behaviors>
        <h:DragMoveBehavior />
    </i:Interaction.Behaviors>
    ...
</Window>

1

এই সব প্রয়োজন!

private void UiElement_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            if (this.WindowState == WindowState.Maximized) // In maximum window state case, window will return normal state and continue moving follow cursor
            {
                this.WindowState = WindowState.Normal;
                Application.Current.MainWindow.Top = 3;// 3 or any where you want to set window location affter return from maximum state
            }
            this.DragMove();
        }
    }

0

ডাব্লুপিএফ এবং উইন্ডোজ ফর্ম উভয়ের জন্য সর্বাধিক ব্যবহারযোগ্য পদ্ধতি, ডাব্লুপিএফ উদাহরণ:

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

    public static void StartDrag(Window window)
    {
        WindowInteropHelper helper = new WindowInteropHelper(window);
        SendMessage(helper.Handle, 161, 2, 0);
    }

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.