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

my $isSkin = 0;

my $SetWindowPos = Win32::API->new("user32","SetWindowPos", "LLLLLLL", "L")
    or die "Failed to load SetWindowPos";

sub SWP_FRAMECHANGED() {32}
sub SWP_NOMOVE() {2}
sub SWP_NOSIZE() {1}
sub SWP_NOZORDER() {4}
sub SWP_NOACTIVATE() {16}
sub WM_NCLBUTTONDOWN() {161}
sub HTCAPTION() {2}
sub SMTO_NORMAL() {0}
sub RGN_AND() {1}
sub RGN_COPY() {5}
sub RGN_DIFF() {4}
sub RGN_OR() {2}
sub RGN_XOR() {3}
sub NULLREGION() {1}
sub SIMPLEREGION() {2}
sub COMPLEXREGION() {3}

# Create the popup menu for use in skin mode

my $popMenu = Win32::GUI::MakeMenu(
				   "Pop" => "Pop",
				   " > &File" => "File",
				   " >> E&xit" => "pop_menu_exit",
				   " > &Skin" => "Skin",
				   " >> &Remove" => "remove_skin_menu",
				   );

# Create the main menu

my $mainMenu = Win32::GUI::MakeMenu(
				   "&File" => "File",
				   " > E&xit" => "pop_menu_exit",
				   );

# Load the skin bmp
my $skin = Win32::GUI::Bitmap->new("skin3.bmp");

# Load the close button bmp (for skin mode)
my $closeBtn = Win32::GUI::Bitmap->new("closebtn.bmp");

#Load the minimize button bmp (for skin mode)
my $minBtn = Win32::GUI::Bitmap->new("minbtn.bmp");


# Get the size of the skin
my ($bWidth, $bHeight, $bColors, $bBPP) = $skin->Info;

# Create the window the same size as the skin.
my $winSkin = Win32::GUI::Window->new(
				      -menu => $mainMenu,
				      -width  => $bWidth,
				      -height => $bHeight,
				      -name   => "winSkin",
				      -text   => "Skin Test",
				      );


# Create a DC to load the skin BMP
my $dcSkin = Win32::GUI::DC::CreateCompatibleDC(0);

# Select the BMP as an object in the DC
$dcSkin->SelectObject($skin);

# Get the 32bit version of the skin image

my @bitmap32 = unpack ("C*", $skin->GetDIBits($dcSkin));

my $p1 = 0;

my @bitmap24;

print "Creating 24bit image\n";

# Convert it to 24 bits
for (my $p = 0; $p < scalar(@bitmap32); $p+= 4) {
    $bitmap24[$p1++] = ($bitmap32[$p] << 16) | (($bitmap32[$p + 1]) << 8)
	| ($bitmap32[$p + 2]);
}

undef(@bitmap32); # Don't need this anymore.

# The transparent color (white)
my $trans = 0xFFFFFF;
my $btnSkin = $winSkin->AddButton(-name => "btnSkin",
				   -text => "Skin",
				   -size => [80, 20],
				   -pos => [115, 110],
				   );

# These 2 buttons are only used when skinned
my $btnClose = $winSkin->AddButton(-name => "btnClose",
				   -size => [20, 20],
				   -pos => [290, 13],
				   -picture => $closeBtn,
				   );

my $btnMin = $winSkin->AddButton(-name => "btnMin",
				   -size => [20, 20],
				   -pos => [270, 13],
				   -picture => $minBtn,
				   );

# Hide the skin buttons, since we don't start in skin mode
$btnClose->Hide();
$btnMin->Hide();

$winSkin->Show();


Win32::GUI::Dialog();

sub winSkin_Paint
{
    my ($dc) = @_;

# Set transparent mode
    $dc->BkMode(1);

    if ($isSkin) {
# Copy the bitmap into the DC
	$dc->BitBlt(0, 0, 320, 340, $dcSkin, 0, 0, 0xCC0020);
	$dc->TextOut(115, 90, "Right Click: Menu");
    }
    return(1);
}

sub winSkin_MouseRightDown
{
    if ($isSkin) {
# Right mouse in skin mode, show the popup menu
	my ($x, $y) = Win32::GUI::GetCursorPos();
	$winSkin->TrackPopupMenu($popMenu->{Pop});
    }
}

sub btnSkin_Click
{
    if ($isSkin) {
	removeRegion();
	$btnSkin->Text("Skin");
	$btnClose->Hide();
	$btnMin->Hide();
    } else {
	addRegion();
	$btnSkin->Text("No Skin");
	$btnClose->Show();
	$btnMin->Show();
    }
}

sub btnMin_Click
{
    $winSkin->Minimize();
}

	
sub btnClose_Click
{
    return(-1);
}

sub winSkin_Terminate
{
    return(-1);
}

sub pop_menu_exit_Click
{
    winSkin_Terminate();
}

sub remove_skin_menu_Click
{
    removeRegion();
}

sub winSkin_MouseDown
{
    return if !$isSkin;

# Allow the skin to be dragged
    Win32::GUI::SendMessage($winSkin, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}


sub removeRegion
{
# Remove the region
    $winSkin->SetWindowRgn(0, 1);

# Restore the caption and borders
    $winSkin->Change(-pushstyle => WS_CAPTION);
    $winSkin->Change(-pushstyle => WS_SIZEBOX);

# Restore the menu
    $winSkin->SetMenu($mainMenu);

# Force the window redraw
    $SetWindowPos->Call($winSkin->{-handle}, 0, 0, 0, 0, 0,
			SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|
			SWP_NOACTIVATE|SWP_NOZORDER);
    $isSkin = 0;
}

sub addRegion
{
    print "Generating region\n";

# Remove the caption and the borders

    $winSkin->Change(-popstyle => WS_CAPTION);
    $winSkin->Change(-popstyle => WS_SIZEBOX);

# Remove the menu
    $winSkin->SetMenu(0);

# Create a region covering the complete bitmap.  Then, we'll remove
# the tranparent pixels.

    my $hRgn = Win32::GUI::Region->CreateRectRgn(0, 0, $bWidth, $bHeight);

    my $pos = 0;

    for (my $y = 0; $y < $bHeight; $y++) {
	for (my $x = 0; $x < $bWidth; $x++) {
# This is a transparent pixel
	    if ($bitmap24[$pos] == $trans) {
		my $x1 = $x;
# For some reason, the image is flipped, so flip it back.
		my $y1 = ($bHeight - $y) - 1;
# Create a region with this pixel
		my $tmpRgn = Win32::GUI::Region->CreateRectRgn($x1, $y1, $x1+1, $y1+1);
# Remove this pixel from the master region
		Win32::GUI::Region::CombineRgn($hRgn, $hRgn, $tmpRgn, RGN_XOR);
# Delete the temp region
		Win32::GUI::DC::DeleteObject($tmpRgn);
	    }
	    $pos++;
	}
    }
# Apply the region
    $winSkin->SetWindowRgn($hRgn, 1);

# Refresh the window
   $SetWindowPos->Call($winSkin->{-handle}, 0, 0, 0, 0, 0,
			SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|
			SWP_NOACTIVATE|SWP_NOZORDER);

    $isSkin = 1;
    print "Region generated\n";
}
