With some help from the Win32 Advanced Perl group, here is what I have so far. I started playing with getWindowDC and Rectangle functions but I am having problems setting the drawn Rectangle as transparent. Also, when I am done dragging, how do I dispose of the DC and refresh all the windows?
#!perl -w
# Left-Click on the target image, and drag
use warnings;
use strict;
use Win32::GUI;
use Win32::API;
use Win32::GUI::BitmapInline();
my $mw = Win32::GUI::Window->new(
-name => "MainWindow",
-title => "Win32::GUI Spy++",
-pos => [100,100],
-size => [100,100],
);
my $cursor = get_cursor();
$mw->AddLabel(
-name => "Target",
-icon => $cursor,
-notify => 1,
-onMouseDown => \&mouseDown,
-onMouseUp => \&mouseUp,
-onMouseMove => \&mouseMove,
);
$mw->Show();
Win32::GUI::Dialog();
exit(0);
###########################
###########################
sub mouseDown{
my $label = shift;
Win32::GUI::SetCursor($cursor);
$label->SetCapture();
return;
}
################
sub mouseUp{
my $label = shift;
$label->ReleaseCapture();
return;
}
#################
sub mouseMove{
my ($label, $x, $y) = @_; # x,y in client co-ordinates
return unless Win32::GUI::GetCapture();
Win32::GUI::SetCursor($cursor);
my $hwnd=getWindowXY($x,$y);
my $class=getWindowClass($hwnd) || '';
my $text=getWindowText($hwnd) || '';
$text=substr($text,0,30) if length($text) > 30;
my $exe=getWindowExe($hwnd) || '';
my ($left,$top,$right,$bottom)=getWindowRect($hwnd);
my $hdc=getWindowDC(getDesktopWindow());
my $ok=drawRectangle($hdc,$left,$top,$right,$bottom);
#print qq|$hwnd\ ($x,$y) [$exe] {$class} "$text"\n|;
return;
}
###############
sub getWindowDC{
#usage: my $hwnd=getWindowDC($hwnd);
#info: returns the handle of a device context for the specified wind
+ow.
my $hwnd=shift || return;
my $GetWindowDC = new Win32::API("user32", "GetWindowDC", ['N'], 'N'
+) || return $^E;
my $hdc=$GetWindowDC->Call($hwnd);
return $hdc;
}
###############
sub getDesktopWindow{
#usage: my $hwnd=getWindowDC($hwnd);
#info: returns the handle of a device context for the specified wind
+ow.
my $GetDesktopWindow = new Win32::API("user32", "GetDesktopWindow",
+[], 'N') || return $^E;
my $hwnd=$GetDesktopWindow->Call();
return $hwnd;
}
###############
sub drawRectangle{
#usage: my $ok=drawRectangle($hdc,$left,$top,$right,$bottom);
#info: returns the handle of a device context for the specified wind
+ow.
my $hdc=shift || return;
my $left=shift || 0;
my $top=shift || 0;
my $right=shift || 0;
my $bottom=shift || 0;
my $Rectangle = new Win32::API("gdi32", "Rectangle", ['N','I','I','I
+','I'], 'N') || return $^E;
my $ok=$Rectangle->Call($hdc,$left,$top,$right,$bottom);
return $hdc;
}
###############
sub getWindowXY{
#usage: my $hwnd=getWindowXY($x,$y);
#info: returns the window handle of window at x,y
my $x=shift || return;
my $y=shift || return;
my $WindowFromPoint = new Win32::API("user32", "WindowFromPoint", ['
+N','N'], 'N') || return $^E;
my $POINT = pack("LL", $x, $y);
return $WindowFromPoint->Call($x,$y);
}
###############
sub getWindowClass{
my $hwnd = shift || return;
my $GetClassName = new Win32::API("user32", "GetClassName", ['N', 'P
+', 'N'], 'N') || return $^E;
my $name = " " x 1024;
my $nameLen = 1024;
my $result = $GetClassName->Call($hwnd, $name, $nameLen);
if($result){return substr($name, 0, $result);}
}
###############
sub getWindowExe {
#GetModuleFileName
my $hwnd = shift || return;
my $GetModuleFileName = new Win32::API("kernel32", "GetModuleFileNam
+e", ['N', 'P', 'N'], 'N') || return "unable to create new API";
my $name = " " x 1024;
my $Len = 1024;
my $result = $GetModuleFileName->Call($hwnd, $name, $Len);
if($result) {return substr($name, 0, $result);}
return "unknown";
}
###############
sub getWindowRect {
my $hwnd = shift || return;
my $GetWindowRect = new Win32::API("user32", "GetWindowRect", ['N',
+'P'], 'N') || return $^E;
my $RECT = pack("iiii", 0, 0);
$GetWindowRect->Call($hwnd, $RECT);
return wantarray ? unpack("iiii", $RECT) : $RECT;
}
###############
sub getWindowText{
my $hwnd = shift || return;
my $GetWindowText = new Win32::API("user32", "GetWindowText", ['N',
+'P', 'N'], 'N') || return $^E;
my $title = " " x 1024;
my $titleLen = 1024;
my $result = $GetWindowText->Call($hwnd, $title, $titleLen);
my $text=substr($title, 0, $result);
if($text){return $text;}
#if no result send a WM_GetText message to the window
my $WmSendMessage = new Win32::API("user32", "SendMessageA", ['N','N
+','N','P'],'N') || return $^E;
my $WM_GETTEXT=13;
my $txt = " " x 2048;
my $textLen = 2048;
$result = $WmSendMessage->Call($hwnd,$WM_GETTEXT, $textLen, $txt);
$text= substr($txt, 0, $result);
return $text;
}
#####################
sub get_cursor{
return Win32::GUI::BitmapInline->newCursor( q(
AAACAAEAICAAAA8AEAAwAQAAFgAAACgAAAAgAAAAQAAAAAEAAQAAAAAAAAEAAAAAAAAAAA
+AAAAAA
AAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAGDAAACbIAABQFA
+AApsoA
AUAFAAECgQACoAqAAqgqgAIBAIACqCqAAqAKgAECgQABQAUAAKbKAABQFAAAJsgAABgwAA
+AHwAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////
+g////g
D///wAf//4gj//8YMf/+ODj//nx8//wMYH/8A4B//AOAf/wDgH/8DGB//nx8//44OP//GD
+H//4gj
///AB///4A////g///////////////////////////////////////8=
) );
}
|