Description: |
Win32 Multiple Clipboards was implemented in a really silly way. I don't know how I missed the obvious. Here's a different implementation that eats a lot less memory, and doesn't use threads and sharing etc...
In fact, what I missed last time was the timer. And since there's no readable documentation for Win32::GUI I came across this by a combination of poking thourgh GUI.pm and luck. It worked out pretty well, and now I'm actually using this.
You will probably need Win32::GUI cause it's not with default ActiveState's installation, otherwise, this should work right out of the box.
Screenshot
Comments and suggestions please. |
#!perl
# copyright (c) Chady Kassouf 2004
# This program is free software, it is distributed under
# the sames terms as Perl itself.
use strict;
use Win32::Clipboard;
use Win32::GUI;
my $empty = '--empty--'; # the empty string
# my $image = '[BITMAP]';
my $DEBUG = 1; # set to 1 for debugging info.
my @boxes; # holds the radiobuttons
my $CLIP; # tied to the clipboard
my @board; # holds the clipboard entries.
push @board, ['', $empty] for 0 .. 4;
tie $CLIP, 'Win32::Clipboard';
# GUI creation.
my $main = Win32::GUI::Window->new(
-name => 'main',
-text => 'Win32 Multiple Clipboards II',
-width => 200,
-height => 150
);
my $icon = Win32::GUI::Icon->new('Note.ico');
my $tray = $main->AddNotifyIcon(
-name => 'tray',
-icon => $icon,
-tip => 'Win32 Multiple Clipboards II'
);
# I found this handled nicely,
# this isn't a busy loop, so no high CPU usage here
my $timer = $main->AddTimer('timer', 100);
foreach (0 .. 4) {
$boxes[$_] = $main->AddRadioButton(
-name => "board$_",
-text => $board[$_]->[1],
-pos => [ 10, 10 + 20 * $_ ],
);
$boxes[$_]->{-width} = 150;
}
$main->Show();
set_clip(1);
Win32::GUI::Dialog();
#####
sub timer_Timer {
my $label;
my $data;
if (tied($CLIP)->IsBitmap()) {
# I tried to handle bitmap data, but it
# gets ruined while copied back and forth;
# when set back, the data become text data.
debug('Bitmap data, skipping');
return;
# $label = $image;
# $data = tied($CLIP)->GetBitmap();
} else {
$label = $CLIP;
$label =~ s/^(.{20})(.*)$/$1... /;
$data = $CLIP;
}
return if $data eq $board[0]->[0];
debug ('Got new clipboard.');
unshift @board, [$data, $label];
pop @board if @board == 4;
}
sub redraw {
for (0..4) {
$boxes[$_]->Checked(0);
$boxes[$_]->{-text} = $board[$_]->[1];
}
}
sub set_clip {
my $which = shift;
redraw();
if ($which) {
$which--;
if ($board[$which]->[1] eq $empty) {
debug('empty slot.');
} else {
debug('Setting clip to: ', $board[$which]->[1]);
$CLIP = $board[$which]->[0];
}
$main->Disable();
$main->Hide();
}
}
# everything I tried doesn't work here.
sub board0_Click {set_clip(1);1;}
sub board1_Click {set_clip(2);1;}
sub board2_Click {set_clip(3);1;}
sub board3_Click {set_clip(4);1;}
sub board4_Click {set_clip(5);1;}
sub tray_Click {
# move the window near the task bar
my $desk = Win32::GUI::GetDesktopWindow();
my $dw = Win32::GUI::Width($desk);
my $dh = Win32::GUI::Height($desk);
my $x = $dw - $main->Width();
# the taskbar is 27 pixels on Xp (no Luna)
my $y = $dh - $main->Height() - 27;
$main->Move($x, $y);
redraw();
$main->Enable();
$main->Show();
1;
}
sub main_Minimize {
$main->Disable();
$main->Hide();
1;
}
sub main_Terminate {
-1;
}
sub debug {
print @_, "\n" if $DEBUG;
}
|