Diskuze: WPF - mouse event

C# .NET .NET (C# a Visual Basic) WPF - mouse event American English version English version

Avatar
martinsakra
Redaktor
Avatar
martinsakra:

Zdravím mám problém s jedným programem ve WPF.
Vytvořil jsem si rectangle do kterýho jsem dal event MouseLefButtonUp,
ale děje se mi že rectangle mi zareaguje až nadruhý klik, nebo když chvíli zustanu myší nad tím konkrétním rectangle.
Zkoušel jsem i MouseUp/Mouse­Down/MouseLef­tButtonDown, ale všechno se to chová stejně, občas se ten klik prostě "nechytí".

Nevím čím to je, třeba takový MouseEnter/Mou­seLeave reagujou okamžitě.

r.MouseLeftButtonUp += Rect_MouseLeftButtonUp;


 private void Rect_MouseLeftButtonUp(object sender, MouseEventArgs e)
       {
           Msquare square = msW [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2];
           square.Rotate(1);
           ((Rectangle)sender).Fill = new ImageBrush(System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(square.Picture.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()));
           ((Rectangle)sender).UpdateLayout();
       }
Odpovědět 10.12.2013 15:55
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
martinsakra
Redaktor
Avatar
martinsakra:

stále nikdo netuší, nebo to tu zapadlo a umřelo?

Nahoru Odpovědět 11.12.2013 10:31
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
coells
Redaktor
Avatar
coells:

Máš tam někde chybu, Rectangle reaguje na úplně normálně na všechny události myši.

Důvody mě napadají dva:

  1. někde cestou zastavíš PreviewMouseLef­tButtonUp nebo MouseLeftButtonUp
  2. je špatně nastavený logický strom
 
Nahoru Odpovědět 11.12.2013 10:50
Avatar
martinsakra
Redaktor
Avatar
Odpovídá na coells
martinsakra:

testování a úpravami jsem došel na zajímavé zjištění, pokud držím ctrl a dělám akci tak se to něděje jinak ano. Viz kód:

private void Rect_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {


            Msquare square;
            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                int selected = SamplesListBox.SelectedIndex;
                square = msW.SquareType [selected];
                msW [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2] = square;
                RectangleFill(rectangles [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2], square.Picture);
            }
            else
            {
                square = msW [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2];
                square.Rotate(1);
                RectangleFill(((Rectangle)sender), square.Picture);
            }
        }

 private void RectangleFill(Rectangle r, System.Drawing.Bitmap b)
        {
            r.Fill = new ImageBrush(System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()));
        }

Je to divný, a nenapadá mě žádný rozumný důvod proč by to mělo fungovat divně. A ano přehodil jsem mousebuttonUp na Down ale žádnej rozdíl. A nemám jinde ve Formu jinej event MouseButtonUp/Down kterej by to odchytil.
Ještě mám pro každej Rectangle danej Focus(), když na něho najedu myší,ale jeho odstraněním se nic nezměnilo.

Nahoru Odpovědět 11.12.2013 11:40
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
coells
Redaktor
Avatar
Odpovídá na martinsakra
coells:

V prvním příspěvku jsi jaksi zapomněl zmínit, že tam máš ListBox. Tvůj handler je nepodstatný, důležitý je zbytek aplikace.

Pokud je Rectangle v jiném controlu, dojde k odchycení PreviewMouseBut­tonUp/Down události a bude to fungovat přesně tak, jak ti to funguje. To je docela rozumný důvod.

 
Nahoru Odpovědět 11.12.2013 12:02
Avatar
martinsakra
Redaktor
Avatar
Odpovídá na coells
martinsakra:

Takže pokud to chápu správně, při kliku se mi teď děje, že se jako první zavolá event PreviewMouseLef­tButtonDown, ten díky tomu že je preview postupuje "z vrchu" od gridu níž. Tj občas se stane že ho odchytne listbox aniž by měl?
Ale jak to vyřešit teda? Zkusil jsem už i hodit list box do canvasu,ale to není řešení.

Nahoru Odpovědět 11.12.2013 16:37
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
coells
Redaktor
Avatar
Odpovídá na martinsakra
coells:

Řekl bych, že by sis rozhodně měl koupit knížku o WPF a něco málo se o něm naučit, než začneš dělat složitější aplikace. Někde ti něco zastavuje zpracování událostí, jenže nemáš tušení, jak RoutedEvents fungují, ani jak zjistit, kde se to děje. Já to na dálku zjistit neumím.

Existuje metoda, která to umí obejít, jenže takový postup narušuje standardní zpracování událostí:

rectangle.AddHandler(Window.MouseLeftButtonUpEvent, new MouseButtonEventHandler(__handler), true);

Tenhle kód mi funguje bez problémů (třikrát Rectangle v ListBoxu):

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox Background="Yellow">
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
        </ListBox>
    </Grid>
</Window>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Rectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        (sender as Rectangle).Fill = Brushes.BlanchedAlmond;
    }

    private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        (sender as Rectangle).Fill = Brushes.Gray;
    }
}
 
Nahoru Odpovědět 11.12.2013 19:53
Avatar
martinsakra
Redaktor
Avatar
Odpovídá na coells
martinsakra:

Pozor mám pocit že jsme si trochu nerozuměli. Já nemám listbox ve kterém jsou rectangly, kdyby to bylo takhle tak bych se prakticky nedivil že mi blbne mousebutton up/down atd.
já mám Grid obsahující A) canvas-1 do kterého vkládám rectangly, B)canvas-2 ve kterem je listbox C) 2 dva buttony
To je ten důvod proč mě to přišlo divný, níkdy po cestě nahoru/dolu nebylo nic co by tomu mohlo bránit

Editováno 11.12.2013 20:11
Nahoru Odpovědět 11.12.2013 20:11
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
coells
Redaktor
Avatar
Odpovídá na martinsakra
coells:

V tom není rozdíl, stále mi to funguje dobře:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Canvas Background="LightBlue" Grid.Row="0">
            <Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="61" Width="107" Canvas.Left="352" Canvas.Top="60" />
            <Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="89" Width="121" Canvas.Left="202" Canvas.Top="32" />
            <Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="91" Width="97" Canvas.Left="60" Canvas.Top="32" />
        </Canvas>
        <ListBox Background="Yellow" Grid.Row="1">
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
            <ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
            </ListBoxItem>
        </ListBox>
    </Grid>
</Window>
 
Nahoru Odpovědět  +1 11.12.2013 20:25
Avatar
martinsakra
Redaktor
Avatar
Odpovídá na coells
martinsakra:

Myslím že problém bude nakonec trochu jiný, vypadá to že pokud se s myší pohne při kliku "nějak" tak se událost nesejme, to co jsem myslel že mám za chybu se děje i tu toho tvýho, prostě velmi rychle měním rectangly a klikám na ně (pokaždé na jiné místo/jiný rectangle) na stejný rychlé klikání funguje. (změnšil jsem si kvuli tomu rectangly a dal je blízko sebe abych to vyzkoušel)

Dík za pomoc

Nahoru Odpovědět 11.12.2013 20:32
Democracy is two wolves and a lamb voting on what to have for lunch. Liberty is a well-armed lamb contesting the vote.
Avatar
coells
Redaktor
Avatar
Odpovídá na martinsakra
coells:

Pověs si event handler přímo na Grid, na konci bude container obsahovat nadřazený canvas a OriginalSource je visual, který splňuje hit-testing.

private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (e.OriginalSource is Rectangle)
    {
        Rectangle r = e.OriginalSource as Rectangle;

        FrameworkElement container = r;
        while (container != null && !(container is Canvas))
            container = container.Parent as FrameworkElement;

        e.Handled = true;
    }
}
 
Nahoru Odpovědět 11.12.2013 20:39
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 11 zpráv z 11.