Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]10325[/thread]

Tk und Win32::GUI -> Tray, diverse Probleme

Leser: 1


<< >> 5 Einträge, 1 Seite
GoodFella
 2007-09-04 19:19
#99083 #99083
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
Hi,
ich versuche gerade, ein venünftiges Tray mit Tk und Win32::GUI zu bauen, vorab erstmal mein Testscript:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use Win32::GUI; 
use Tk; 
use strict;
use warnings;

my $current_id = 1;
my $is_in_tray = 0;
my $unmap_trigger = 0;

my $main_win32 = new Win32::GUI::DialogBox( -width => 0, -height => 0, -name => 'MainWindow' );
my $icon = new Win32::GUI::Icon( 'test.ico' ); 

my $main = MainWindow -> new; 
$main->geometry('100x100'); 
#$main->overrideredirect(1);

$main->protocol( 'WM_DELETE_WINDOW' => [ \&minimize_to_tray ] ); 
$main->bind("<Unmap>",sub{ $unmap_trigger++; 
                           if ($unmap_trigger % 3 == 0)
                            { 
                              $main->withdraw;                              
                              &minimize_to_tray; 
                            }
                         }
           ); 

my $btn_minimize = $main->Button( -text => 'Minimize', -command => [ \&minimize_to_tray ] );
my $btn_close = $main->Button( -text => 'Close', -command => [ \&clean_exit ] );

$btn_minimize->place( -x => 10, -y => 5 );
$btn_close->place( -x => 10, -y => 30 );

MainLoop; 

sub context_menu
 { 
  my $popup = $main->Menu( Name => 'popupMenu', -tearoff => 0 ); 
  $popup->command( -label => 'Beenden', -command => [ \&clean_exit ] ); 
  $popup->Popup( -popover => 'cursor', -popanchor => 'nw' ); 
  return 1;
 } 

sub raise_main
 {
  $is_in_tray = 0;
  $main->deiconify;
  $main->raise;
  $main->focus;
  return -1;
 }

sub minimize_to_tray
 {
  $is_in_tray = 1;
  $main->withdraw;
  new Win32::GUI::NotifyIcon( $main_win32, 
                              -name => "Notify", 
                              -id => ++$current_id,
                              -icon => $icon, 
                              -tip => "M.A.M.A.",
                              -onClick => sub { &raise_main; },
                              -onRightClick => sub { &context_menu; } ); 
  my $call = Win32::GUI::Dialog(); 
  $main_win32->Notify->Delete( -id => $current_id ); 
 }

sub clean_exit { $main_win32->Notify->Delete( -id => $current_id ) if ($is_in_tray == 1); exit(0);  } 


Zum Test muss sich test.ico im selben Verzeichnis befinden.

Folgendes funktioniert nicht wie erwartet:

1. Klickt man auf den Minimize-Button, dann Rechtsclick auf das Tray-Symbol, und schliesslich auf Beenden, dann kommt ein merkwürdiger OK-Abbrechen Dialog mit dem Text "_TK_EXIT_(0)" und dem Titel "RightClick", ausserdem bleibt das Programm dann im Speicher. Der Close-Button jedoch funktioniert bestens.

2. Das Minimieren, welches ich per unmap abfange, scheint mir sehr unsauber zu sein, gibts da nicht besseres?

3. Wechsle ich mehr als 1 Mal zwischen Tray und "Normal", so erscheint beim erneuten Aufruf des Tray KEIN Tray-Symbol, sondern gar nichts, das Programm bleibt im Speicher und man hat keine Möglichkeit mehr, es zu beenden (ausser mit dem Taskmanager)
Ich habe zuerst gedacht, es läge an der id, da diese ja gelöscht wird.. habe also die id sich erhöhen lassen, leider kein Effekt.


Habe ich etwas übersehen? Habt ihr eine Idee woran das liegt? Ich sitze jetzt schon seit 2 Tagen daran...
ptk
 2007-09-04 22:02
#99091 #99091
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Zu 1: Geht es, wenn du statt exit() CORE::exit() verwendest?

Zu 2: Mir ist kein Event, der getriggert wird, wenn minimiert wird. Unter Umständen wird auch <Configure> getriggert, aber dieses Event gibt es auch beim Verschieben, Vergrößern etc. <Unmap> scheint mir erstmal gut genug.

Zu 3: Vielleicht sollte man NotifyIcon wiederverwenden? Habe aber keine Ahnung von Win32-Programmierung.
GoodFella
 2007-09-05 12:49
#99113 #99113
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
ptk+2007-09-04 20:02:26--
Zu 1: Geht es, wenn du statt exit() CORE::exit() verwendest?

Zu 2: Mir ist kein Event, der getriggert wird, wenn minimiert wird. Unter Umständen wird auch <Configure> getriggert, aber dieses Event gibt es auch beim Verschieben, Vergrößern etc. <Unmap> scheint mir erstmal gut genug.

Zu 3: Vielleicht sollte man NotifyIcon wiederverwenden? Habe aber keine Ahnung von Win32-Programmierung.


1: Werde es versuchen, sage dann nochmal bescheid [EDIT] Funktioniert!! Danke..[/EDIT]

2: ok, dann muss ich mich damit wohl zufrieden geben..

3: Das Problem ist, dass es in NotifyIcon einen Bug gibt, das Icon verschwindet nur aus dem Tray, wenn es explizit gelöscht wird (es ginge sonst nichtmal beim Programmende weg), wiederverwenden ist keine Option.
GoodFella
 2007-09-05 19:03
#99134 #99134
User since
2007-01-09
192 Artikel
BenutzerIn
[default_avatar]
Nach langem Probieren habe ich nun eine vollständig funktionierende Version, die z.B. auch Icon-Animation zulassen würde, wäre eigentlich perfekt für ein Wiki ^^
Ich habe Win32::GUI::Dialog weggelassen und schon ging einiges, was vorher Probleme gemacht hatte. Wegen 2: <Unmap> feuert 1,2 oder 3 Mal je nach Aktion, da erschien es mir sinnvoll, das etwas umzuschreiben.
Die Idee mit dem verschwindenden und wieder auftauchenden Icon habe ich allerdings beerdigt, hat nach Stunden immer noch nicht funktioniert. (Man könnte das Icon allerdings gegen ein 1x1 Pixel-Icon austauschen..)

Eine Sache macht mir allerdings noch Kopfzerbrechen: Klickt man mehrfach und schnell hintereinander mit der rechten und linken Maustaste auf das Icon, lässt sich kein Kontextmenü mehr öffnen, nachdem es den Focus verloren hatte.
Ausserdem treten sporadisch "Perl.exe hat ein Problem festgestellt und muss beendet werden" Fehlermeldungen auf.. ist allerdings eine Weile her dass ich die letzte gesehen habe, kann also schon aus dem Code eliminiert sein.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use Win32::GUI; 
use Tk; 
use strict;
use warnings;

# Win32::GUI 
my $main_win32 = new Win32::GUI::DialogBox( -width => 0, -height => 0, -name => 'TrayWindow' );
my $icon_nr = 0;
my @icon = (new Win32::GUI::Icon( 'test.ico' ), new Win32::GUI::Icon( 'test2.ico' )); 
new Win32::GUI::NotifyIcon( $main_win32, 
                            -name => "Notify", 
                            -id => 255, 
                            -icon => $icon[$icon_nr], 
                            -tip => "mails and more Auftragsmanagement",
                            -onClick => sub { &toggle_main; },  
                            -onRightClick => sub { &context_menu; } ); 

#Tk 
my $main = MainWindow->new; 
my $btn_close = $main->Button( -text => ' Beenden ', -command => sub { &clean_exit } )->pack();
my $btn_switch_icon = $main->Button( -text => ' Icon ändern ', -command => sub { &toggle_icon } )->pack();

#Minimieren- und X-Button ins Tray leiten
$main->protocol( 'WM_DELETE_WINDOW' => sub { $main->withdraw; } ); 
$main->bind( "<Unmap>", sub { $main->withdraw if ($main->state eq 'iconic'); } ); 

MainLoop; 

#Rechtsklickmenü aufrufen
sub context_menu
 { 
  my $popup = $main->Menu( Name => 'popupMenu', -tearoff => 0 ); 
  $popup->command( -label => 'm.a.m.A. Beenden', -command => sub { &clean_exit } ); 
  $popup->Popup( -popover => 'cursor', -popanchor => 'nw' ); 
  return 1;
 } 

#Hauptfenster verstecken / anzeigen
sub toggle_main
 {
  if ($main->state eq 'withdrawn')
   {
    $main->deiconify;
    $main->raise;
    $main->focus;  
   }
  else { $main->withdraw; }
 }

#Icon verändern
sub toggle_icon
 {
   $icon_nr = !$icon_nr;
   Win32::GUI::NotifyIcon::Modify( $main_win32,
                                   -id => 255,
                                   -icon => $icon[$icon_nr],
                                   -tip => ' verändertes Icon ' ); 
 }

#TrayIcon erntfernen und Beenden
sub clean_exit { $main_win32->Notify->Delete( -id => 255 ); CORE::exit;  } 


[EDIT]
Eine Sache ist mir gerade aufgefallen: Toplevel Widgets sind vom withdraw des MainWindow nicht betroffen.. wie kann ich die (ausser manuell einzeln) automatisch mitverschwinden lassen?[/EDIT]
ptk
 2007-09-05 22:22
#99140 #99140
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Quote
Eine Sache ist mir gerade aufgefallen: Toplevel Widgets sind vom withdraw des MainWindow nicht betroffen.. wie kann ich die (ausser manuell einzeln) automatisch mitverschwinden lassen?
Wenn es sich um transiente Toplevels handelt, dann verschwinden diese auch üblicherweise (abhängig vom Windowmanager) beim withdraw.

Ansonsten kannst du dir was mit Walk basteln. Ungetestet:
Code: (dl )
$mw->Walk(sub { $_->isa("Tk::Toplevel") and $_->withdraw })

<< >> 5 Einträge, 1 Seite



View all threads created 2007-09-04 19:19.