Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Win32 Multiple Clipboards

by Chady (Priest)
on Apr 20, 2004 at 13:27 UTC ( [id://346620]=sourcecode: print w/replies, xml ) Need Help??
Category: Win32 Stuff
Author/Contact Info Chady
Description:

I love the idea of Klipper in KDE, and I always lack that functionality in Windows; you copy some text, move around to another application, select a new text to replace and accidentally hit Ctrl+C instead of Ctrl+V. So your old text is gone, and you have to find it back and copy again.

This is an attempt to make a small tray application to keep your latest 5 clipboard copies and let you choose one of them.

Requirements:

  • required perl 5.8.0 or higher.
  • Win32::GUI.
  • Win32::Clipboard blocks, so I had to put this in threads.
  • We need to share data between threads, thus threads::shared.
  • Problem: we cannot splice the array, so I'm deleting the array elements manually.

Bugs:

  • uses a lot of memory. Not recommended if you copy around huge amounts of data.
  • Can only handle text.

I'm using ActivPerl 5.8.3 and run this with ``wperl clip.pl'' from a startup script. You will also need an icon of some sort.

Please post you comments, suggestions.

Update: Screenshot

#!perl

# copyright (c) Chady Kassouf 2004
# This program is free software, it is distributed  under 
# the sames terms as Perl itself.


use strict;

use threads;
use threads::shared;
use Win32::Clipboard;
use Win32::GUI;

my @board : shared;
push @board, '--empty--' for 0 .. 4;

my @boxes;
my $CLIP = Win32::Clipboard();

my $thread = threads->create("monitor");

my $main = Win32::GUI::Window->new(
    -name    =>    'main',
    -text    =>    'Win32 Multiple Clipboard',
    -width    =>    200,
    -height    =>    150
);

my $icon = Win32::GUI::Icon->new('Note.ico');
my $tray = $main->AddNotifyIcon(
    -name    =>    'tray',
    -icon    =>    $icon,
    -tip    =>    'Win32 Multiple Clipboard'
);


foreach (0 .. 4) {
    my $label = $board[$_];
    $label =~ s/^(.{10})(.*)$/$1... /;
    $boxes[$_] = $main->AddRadioButton(
        -name => "board$_",
                -text => $label,
                -pos  => [ 10, 10 + 20 * $_ ],
    );
    $boxes[$_]->{-width} = 150;
}


$main->Show();
set_clip(1);
Win32::GUI::Dialog();

##

sub set_clip {
    my $which = shift;
    $boxes[$_]->Checked(0) for 0..4;
    $boxes[$_]->{-text} = $board[$_] for 0..4;
    if ($which) {
        $which--;
        my $d = $board[$which];
        $CLIP->Set($d);
        $main->Disable();
        $main->Hide();    
    }    
}

# there must be a better way for this.
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);
    
    $main->Enable();
    $main->Show();
    set_clip(0);
    1;
}

# this runs in another thread because it blo
sub monitor {
    
    {
        print "[MONITOR]: Waiting for clipboard.\n";
        $CLIP->WaitForChange();
        print "[MONITOR]: Clipboard changed.\n";
        my $data = $CLIP->Get();
        last if $data eq '___EXIT___';
        # skip empty and same requests
        redo if ($data eq $board[0] || $data eq '--empty--');

        unshift @board, $data;
        # splice @board, 5;
        delete $board[$_] for 5 .. $#board + 1;
        redo;
    }
}


sub main_Minimize {
    $main->Disable();
    $main->Hide();
    1;
}


sub main_Terminate {
    $CLIP->Set('___EXIT___');
    $thread->join();
    $CLIP->Set($board[0]); # make sure we can start next time.
    -1;
}
Replies are listed 'Best First'.
Re: Win32 Multiple Clipboards
by jeffa (Bishop) on Apr 20, 2004 at 14:02 UTC

    # there must be a better way for this. 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;}
    You bet there is. One better way is via AUTOLOAD:
    use vars '$AUTOLOAD'; sub AUTOLOAD { my ($numb) = $AUTOLOAD =~ /.*::board(\d+)_Click/; # error checking here :) set_clip($numb); }

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://346620]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2024-04-25 07:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found