=head1 NAME

Win32::GUI::AdHoc -- Small utility routines for Win32::GUI

=head1 DESCRIPTION

This is a small collection of routines to aid you when
coding Win32::GUI applications.

No symbols are exported.

=head1 SYNOPSIS

	#Block GUI warnings
	Win32::GUI::AdHoc::blockGUIWarnings();

=cut





package Win32::GUI::AdHoc;





use strict;
use Win32::API;
use Win32::GUI;

use Data::Dumper;





=head1 CONSTANTS

=head2 Custom message to exit from the Dialog() function.

	WM_EXITLOOP
	WM_APP

=cut
use constant WM_APP				=> 0x8000;			#From winuser.h (Visual Studio)
use constant WM_EXITLOOP		=> WM_APP + 1;		#From GUI.xs


=head2 RichEdit

	EM_LINESCROLL
	EM_SETPARAFORMAT

=cut
use constant EM_LINESCROLL		=> 182;				#From podview.pl
use constant EM_SETPARAFORMAT	=> 0x447;			#From the Win32 SDK


=head2 To make combo boxed non-editable

	CBS_DROPDOWNLIST
	CBS_DISABLENOSCROLL
=cut
use constant CBS_DROPDOWNLIST => 0x0003;			#From winuser.h
use constant CBS_DISABLENOSCROLL => 0x0800;


=head2 ExWindow

	GWL_EXSTYLE
	WS_EX_TOOLWINDOW

=cut

use constant GWL_EXSTYLE => (-20);					#From wiuser.h
#use constant WS_EX_TOOLWINDOW => 0x00000080;		#From wiuser.h


=head2 Label image options

	SS_BITMAP

=cut
use constant SS_BITMAP => 0x0000000E;


=head2 Drag-drop

	WM_DROPFILES

=cut
use constant WM_DROPFILES => 0x0233;


=head2 Keys

Key codes for use with e.g. GetAsyncKeyState()

=cut
use constant VK_SHIFT => 0x10;
use constant VK_CONTROL => 0x11;
use constant VK_MENU => 0x12;





=head1 ROUTINES

=head2 blockGUIWarnings()

Install a warning handler to block certain types of warnings
that occur frequently when using Win32::GUI.

Rationale: Well... Win32::GUI sprinkles warnings left and
right, which makes it difficult to discern your own
warnings. And, it's plain annoying.

Original idea: Eric Bennett on the Win32::GUI mailing list.

=cut
sub blockGUIWarnings { my $self = shift;

	$SIG{'__WARN__'} = sub {
		my ($warning) = @_;

		if($warning =~ /^Use of uninitialized value in subroutine entry at .+? line \d+?\.$/) {
			return(0);
			}

		if($warning =~ m{cleanup.*EXISTS.*Win32/GUI\.pm line \d+? during global destruction\.$}) {
			return(0);
			}

		print STDERR $warning;
		};

	return(1);
	}





=head2 exitDialog($winSomewindow)

Exit from the Win32::GUI::Dialog event loop.

$winSomewindow -- A Win32::GUI window object we can send the
WM_EXITLOOP message to.

Return 1 on success, else 0.

=cut
sub exitDialog {
	my ($winSomewindow) = @_;

	$winSomewindow->PostMessage(WM_EXITLOOP, -1, 0);

	return(1);
	}





=head2 richEditScroll($reControl, $noCol, $noLines)

Scroll $reControl so that $noLines is the first visible
line.

Return 1 on success, else 0.

The actual functionality is taken from the podview.pl sample
file.

=cut
sub richEditScroll {
	my ($reControl, $noCol, $noLines) = @_;

	my $diff = $noLines - $reControl->FirstVisibleLine();
	$reControl->SendMessage(EM_LINESCROLL, $noCol, $diff);

	return(1);
	}





=head2 richEditTabstops($reControl, $tabSize)

Set the tab size in $reControl to $tabSize pixels wide.

Return 1 on success, else 0.

The actual functionality is taken from the wex.pl program by
Harald Piske.

=cut
my $rsSendMessage = new Win32::API ('User32', $_ = 'SendMessage', "INIP", "I");
sub richEditTabsizePixels {
	my ($reControl, $tabSize) = @_;

	my $formatParams = 'VVvvV3vvV32';
	my $params = pack($formatParams,
			0,						# cbSize (filled in later)
			0x10,					# dwMask
			0,						# wNumbering
			0,						# wReserved
			0,						# dxStartIndent
			0,						# dxRightIndent
			0,						# dxOffset
			2,						# wAlignment
			32,						# cTabCount
			map { $tabSize * $_ }
					(1..32),		# rgxTabs[MAX_TAB_STOPS]
			);
	my $lenParam = pack(substr($formatParams, 0, 1), length($params));
	substr($params, 0, length($lenParam)) = $lenParam;

	$rsSendMessage->Call($reControl->{-handle}, EM_SETPARAFORMAT, 0, $params);

	return(1);
	}





=head2 GetSysColorBrush($color)

Return a handle identifying a logical brush that corresponds 
to the specified color index. See the color contants above.

Example: COLOR_BTNFACE

=cut
my $rsGetSysColorBrush = new Win32::API("user32", "GetSysColorBrush", "N", "N");
sub GetSysColorBrush {
	my ($color) = @_;

	return( $rsGetSysColorBrush->Call($color) );
	}





=head2 GetSysColor($color)

Return the current color of the specified display element. 
Display elements are the parts of a window and the Windows 
display that appear on the system display screen. 

Example: COLOR_BTNFACE

=cut
my $rsGetSysColor = new Win32::API("user32", "GetSysColor", "N", "N");
sub GetSysColor {
	my ($color) = @_;

	return( $rsGetSysColor->Call($color) );
	}





=head2 GetAsyncKeyState($keyCode)

Retrieve the status of the specified virtual key. The status 
specifies whether the key is up, down, or toggled (on, off--
alternating each time the key is pressed). 

$keyCode -- If a..z0..9, use the ASCII code. Otherwise, use 
a virtual key code. Example: VK_SHIFT

Return 1 if the key is depressed, 0 if it's not.

=cut
my $rsGetAsyncKeyState = new Win32::API("user32", "GetAsyncKeyState", "N", "I");
sub GetAsyncKeyState {
	my ($keyCode) = @_;

	my $ret = $rsGetAsyncKeyState->Call($keyCode);
#print "ret = $ret\n";
	return( $ret & 1 );
	}





=head2 GetKeyboardState()

Retrieve the status of the specified virtual key. The status 
specifies whether the key is up, down, or toggled (on, off--
alternating each time the key is pressed). 

$keyCode -- If a..z0..9, use the ASCII code. Otherwise, use 
a virtual key code. Example: VK_SHIFT

Return 1 if the key is depressed, 0 if it's not.

=cut
my $rsGetKeyboardState = new Win32::API("user32", "GetKeyboardState", "P", "I");
sub GetKeyboardState {

	my $buf = " " x 256;
	$rsGetKeyboardState->Call($buf) or return([]);
	
	my @aState = map { $_ & 128 } unpack("C256", $buf);
#print "$aState[0x25]\n";
	return( \@aState );
	}





=head2 DrawFrameControl($dcDev, $left, $top, $right, $bottom, $type, $state)

Draw a frame control of the specified type and style.

$dcDev -- Identifies the device context of the window in 
which to draw the control.

Return 1 if the key is depressed, 0 if it's not.

=cut
my $rsDrawFrameControl = new Win32::API("user32", "DrawFrameControl", "NPII", "I");
sub DrawFrameControl {
	my ($dcDev, $left, $top, $right, $bottom, $type, $state) = @_;

	my $rect = pack("llll", $left, $top, $right, $bottom);
	my $ret = $rsDrawFrameControl->Call($dcDev->{-handle}, $rect, $type, $state);

	return( $ret );
	}





=head2 DrawIcon($dcDev, $left, $top, $icoIcon)

Draw $bmBitmapIcon on $dcDev at $left, $top.

$dcDev -- Identifies the device context of the window in 
which to draw.

$icoIcon -- Win32::GUI::Icon object.

Note: This is untested, but could very well work :)

Return 1 if the key is depressed, 0 if it's not.

=cut
my $rsDrawIcon = new Win32::API("user32", "DrawIcon", "NNNN", "I");
sub DrawIcon {
	my ($dcDev, $left, $top, $icoIcon) = @_;

	my $ret = $rsDrawIcon->Call($dcDev->{-handle}, int($left), int($top), $icoIcon->{-handle});

	return( $ret );
	}





=head2 SetBrushOrgEx($dcDev, $left, $top)

Set the brush origin to $left, $top.

Return two element array with the old origin, or () on 
errors.

=cut
my $rsSetBrushOrgEx = new Win32::API("gdi32", "SetBrushOrgEx", "NNNP", "I") or die();
sub SetBrushOrgEx {
	my ($dcDev, $left, $top) = @_;

	my $old = "  " x 2;
	$rsSetBrushOrgEx->Call($dcDev->{-handle}, $left, $top, $old) or return();
	my @aRet = unpack("LL", $old);

	return(@aRet);
	}





1;





#EOF
