2016-04-22 20 views
0

Ich möchte nur die Taskleiste Schaltfläche meiner Winforms-Anwendung durch ein Taskleistensymbol ersetzen. Das heißt, wenn der Benutzer mit der linken Maustaste auf das Symbol klickt, sollte das Formular aktiviert werden, wenn es nicht fokussiert wurde, andernfalls minimiert oder ausgeblendet.Korrekte Art, mein MainForm von einer NotifyIcon zu aktivieren, wenn es nicht bereits fokussiert war

Ich lese viele und viele Artikel über die ordnungsgemäße Verwendung eines NotifyIcon, und es scheint, dass ich eine haschische Lösung akzeptieren muss. Also, was ist der richtige Weg?

Ich habe es meist zu laufen, aber jetzt bin ich fest auf erkennen, ob mein Formular bereits aktiv war - weil beim Klicken auf das Symbol, verliert das Formular den Fokus, so dass ich die Focused Eigenschaft nicht überprüfen kann.

Der folgende Code löst dies noch nicht, also wenn das Formular nur von anderen Fenstern ausgeblendet wurde, müssen Sie zweimal klicken, weil der erste Klick minimiert.

Wie kann es verbessert werden?

private void FormMain_Resize(object sender, EventArgs e) 
    { 
     if (WindowState == FormWindowState.Minimized) 
      Hide(); 
    } 

    private void notifyIcon_MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left) 
      if (WindowState == FormWindowState.Minimized) { 
       WindowState = FormWindowState.Normal; 
       Show(); 
       Activate(); 
      } 
      else { 
       Hide(); 
       WindowState = FormWindowState.Minimized; 
      } 
    } 

(ich auch nicht verstehen, warum die Click Ereignis ausgelöst wird auf der rechten Maustaste, die bereits über das Kontextmenü in meinem Fall öffnet ...)

(Und natürlich wäre es schön, zu habe eine richtige Minimierung Animation, aber es gibt andere Fragen hier, wo dies nicht wirklich gelöst wurde)

(Ich weiß, ich sagte Focused, aber wenn das Formular bereits vollständig sichtbar war (aber vielleicht nicht fokussiert), und der Benutzer klickt auf das Tray-Icon, er möchte es wahrscheinlich ausblenden)

+2

Sie müssen zu Hacks greifen seit dem Moment, bevor Sie auf NotifyIcon klicken, wird Ihr Formular deaktiviert. Viele Hacks versuchen, einen Timer im MouseMove-Ereignis zu starten und versuchen, ein MouseLeave-Ereignis zu erstellen, das mit diesem Symbol verbunden ist, aber keines davon ist zuverlässig, da Windows die Rechteckbegrenzungen Ihres Symbols nicht bereitstellt. – LarsTech

+0

@LarsTech dann ist es vielleicht besser, einen Timer bei Deaktivierung des Formulars zu starten ... Aber das würde mir nicht gefallen. –

Antwort

1

@LarsTech schlug einen Hack mit einem Timer vor, und das funktioniert, danke, aber ich hoffe immer noch auf bessere Lösungen oder Verbesserungen.

Vielleicht interessant: Ich habe auch einen Teil des Animationsproblems gehackt - wenn es keine Taskbar-Schaltfläche gibt, stammt die Animation von dem Ort, an dem sich das minimierte Formular befindet. Sie können es sichtbar machen, indem Sie nach dem Minimieren Show() aufrufen. Es befindet sich in der unteren linken Ecke des Bildschirms und es ist nicht möglich, es zu verschieben, indem Sie die Left Eigenschaft festlegen. Also habe ich winapi direkt benutzt und es funktioniert! Leider nur für die Restore-Animation, weil ich nicht weiß, wie man die minimierte Position vor dem Minimieren setzt. Hide() deaktiviert die Animation sowieso, also müsste ich es verzögern ...

Das ist alles so enttäuschend! Warum gibt es keine schöne Lösung? Ich kann nie sicher sein, ob es in jedem Szenario funktioniert. Zum Beispiel funktionierte es auf einem Rechner gut mit einem 100ms-Timer, aber auf einem anderen brauchte ich 200ms. Also schlage ich vor, mindestens 500ms zu haben.

[DllImport("user32.dll", SetLastError = true)] 
static extern bool MoveWindow(IntPtr hWnd, 
    int X, int Y, int nWidth, int nHeight, bool bRepaint); 

private void FormMain_Resize(object sender, EventArgs e) 
{ 
    if (!ShowInTaskbar && WindowState == FormWindowState.Minimized) { 
     Hide(); 
     //Move the invisible minimized window near the tray notification area 
     if (!MoveWindow(Handle, Screen.PrimaryScreen.WorkingArea.Left 
       + Screen.PrimaryScreen.WorkingArea.Width - Width - 100, 
       Top, Width, Height, false)) 
      throw new Win32Exception(); 
    } 
} 

private void notifyIcon_MouseDown(object sender, MouseEventArgs e) 
{ 
    if (e.Button == MouseButtons.Left) 
     if (WindowState == FormWindowState.Minimized || !timer.Enabled) { 
      Show(); 
      WindowState = FormWindowState.Normal; 
      Activate(); 
     } 
     else { 
      WindowState = FormWindowState.Minimized; 
      //FormMain_Resize will be called after this 
     } 
} 

private void FormMain_Deactivate(object sender, EventArgs e) 
{ 
    timer.Start(); 
} 

private void timer_Tick(object sender, EventArgs e) 
{ 
    timer.Stop(); 
} 

//other free goodies not mentioned before... 

private void taskbarToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    ShowInTaskbar = !ShowInTaskbar; 
    taskbarToolStripMenuItem.Checked = ShowInTaskbar; 
} 

private void priorityToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    //Set the process priority from ToolStripMenuItem.Tag 
    //Normal = 32, Idle = 64, High = 128, BelowNormal = 16384, AboveNormal = 32768 
    Process.GetCurrentProcess().PriorityClass 
     = (ProcessPriorityClass)int.Parse((sender as ToolStripMenuItem).Tag.ToString()); 
    foreach (ToolStripMenuItem item in contextMenuStrip.Items) 
     if (item.Tag != null) 
      item.Checked = item.Equals(sender); 
} 

private void exitToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    Close(); 
}