Jonathan,

You've probably become bored with this and moved onto something else,
but I finally got it and I think that some of the techniques may be
useful elsewhere. The problem was, indeed, that I was writing to a copy
of the structure rather than the structure itself. As far as I can see,
although you can dereference a pointer using pack and unpack, there is
no way to *write* to the referent from pure perl. The trick was to copy
the memory using the Windows function via Win32::API. It's ugly and a
kludge, but it works. It would be easy enough to extend to subitems or
to change fonts. MSDN explains the process; just search for
NM_CUSTOMDRAW. Here's the code:

###############################

#!perl -w

use strict;
use Win32();
use Win32::API;
use Win32::GUI;

use constant WM_NOTIFY                  => 0x4E;
use constant NM_CUSTOMDRAW              => -12;
use constant CDRF_NEWFONT               => 2;
use constant CDRF_NOTIFYITEMDRAW        => 32;
use constant CDDS_PREPAINT              => 1;
use constant CDDS_ITEMPREPAINT  => 65537;
use constant CLR_RED                    => "0000FF";
use constant CLR_GREEN                  => "00FF00";
use constant CLR_BLUE                   => "FF0000";
use constant CLR_WHITE                  => "FFFFFF";
use constant CLR_BLACK                  => "000000";

my $mw = new Win32::GUI::Window(
    -name    => "mw",
    -text        => "Colour Test",
    -size    => [ 200, 200 ],
    -pos         => [ 200, 200 ],
);

sub mw_Terminate { return -1 }

$mw->AddListView(
    -name         => "lvList",
    -pos      => [ 0, 0 ],
    -size     => [ 190, 125 ],
);

$mw->lvList->InsertColumn(
    -index       => 0,
    -text        => "Item",
);

$mw->lvList->ColumnWidth(0,180);

$mw->lvList->InsertItem(-text => "One");
$mw->lvList->InsertItem(-text => "Two");
$mw->lvList->InsertItem(-text => "Three");
$mw->lvList->InsertItem(-text => "Four");

$mw->lvList->TextColor(hex(CLR_RED));

$mw->lvList->Hook(NM_CUSTOMDRAW, \&lvList_CustomDraw);

my $CopyMemory=new Win32::API("kernel32", "RtlMoveMemory", "NPI", "V");
defined $CopyMemory or die "Can't find CopyMemory";

sub lvList_CustomDraw{
        my ($object, $wParam, $lParam, $type, $msgcode)[EMAIL PROTECTED];
        return 1 if $type!=WM_NOTIFY;

        my ($dwDrawStage, $dwItemSpec)=
                        unpack("x12Ix20i", unpack("P40",
pack("L",$lParam)));

        if ($dwDrawStage==CDDS_PREPAINT) {
                $object->Result(CDRF_NOTIFYITEMDRAW);
        } elsif ($dwDrawStage==CDDS_ITEMPREPAINT) {
                my $clrText;
                if ($dwItemSpec==1) {
                        $clrText=pack("II",hex(CLR_BLUE),hex(CLR_WHITE))
                } elsif ($dwItemSpec==2) {
        
$clrText=pack("II",hex(CLR_GREEN),hex(CLR_BLACK))
                } else {
                        return
                }
                $CopyMemory->Call($lParam+48, $clrText, 8);
                $object->Result(CDRF_NEWFONT);
        }
}

$mw->Show;
$mw->lvList->SetFocus();
Win32::GUI::Dialog();

##########################################

Glenn

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of
Glenn W Munroe
Sent: Tuesday, 24 February, 2004 13:36
To: 'Jonathan Southwick'; perl-win32-gui-users@lists.sourceforge.net
Subject: RE: [perl-win32-gui-users] Setting individual item properties

Jonathan,

I've been doing a lot of work with ListViews recently, so I decided to
have a look at this. One way to go is to use Steve Pick's Hook method to
grab the NM_CUSTOMDRAW notification (though there may be an easier way).
I got most of the way, but have been tearing my hair out trying to
figure out how to dereference the pointer. I just can't seem to get the
right combination of packs and unpacks; perhaps somebody here can point
out my mistake. I have access to the structure, but it appears to be
only a *copy* of the structure.

If you return the commented CDRF_SKIPDEFAULT instead of CDRF_NEWFONT the
item isn't drawn at all, so I think that shows that the idea is
basically sound.

Here is the code:

####################################

use strict;
use Win32();
use Win32::GUI;

use constant WM_NOTIFY                  => 0x4E;
use constant NM_CUSTOMDRAW              => -12;
use constant CDRF_DODEFAULT             => 0;
use constant CDRF_NEWFONT               => 2;
use constant CDRF_SKIPDEFAULT           => 4;
use constant CDRF_NOTIFYITEMDRAW        => 32;
use constant CDDS_PREPAINT              => 1;
use constant CDDS_ITEMPREPAINT  => 65537;

my $mw = new Win32::GUI::Window(
        -name  => "mw",
        -text    => "Colour Test",
        -size  => [ 200, 200 ],
        -pos     => [ 200, 200 ],
);

sub mw_Terminate { return -1 }

$mw->AddListView(
        -name     => "lvList",
        -pos    => [ 0, 0 ],
        -size   => [ 190, 125 ],
);

$mw->lvList->InsertColumn(
        -index => 0,
        -text    => "Item",
);

$mw->lvList->ColumnWidth(0,180);

$mw->lvList->InsertItem(-text => "One");
$mw->lvList->InsertItem(-text => "Two");
$mw->lvList->InsertItem(-text => "Three");
$mw->lvList->InsertItem(-text => "Four");

$mw->lvList->TextColor(hex("0000FF"));

$mw->lvList->Hook(NM_CUSTOMDRAW, \&lvList_CustomDraw);

sub lvList_CustomDraw{
        my ($object, $wParam, $lParam, $type, $msgcode)[EMAIL PROTECTED];
        return 1 if $type!=WM_NOTIFY;

        my $struct=unpack("P52",pack("L",$lParam));
        my ($dwDrawStage, $dwItemSpec, $clrText)=
                unpack("x12Ix20ix8I", $struct);

        if ($dwDrawStage==CDDS_PREPAINT) {
                $object->Result(CDRF_NOTIFYITEMDRAW);
                return;
        }

        if ($dwDrawStage==CDDS_ITEMPREPAINT and $dwItemSpec==1) {
                printf ("%X %d %08X\n", $dwDrawStage, $dwItemSpec,
$clrText);

                $struct=pack("x48I",hex("FF0000"));

                ($dwDrawStage, $dwItemSpec, $clrText) = 
                        unpack("x12Ix20ix8II",unpack("P52", pack("L",
$lParam)));
                printf ("%X %d %08X\n", $dwDrawStage, $dwItemSpec,
$clrText);
                $object->Result(CDRF_NEWFONT);
#               $object->Result(CDRF_SKIPDEFAULT);
                return;
        }
        $object->Result(CDRF_NOTIFYITEMDRAW);
}


$mw->Show;
$mw->lvList->SetFocus();
Win32::GUI::Dialog();

######################################


Glenn

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of
Jonathan Southwick
Sent: Friday, 20 February, 2004 16:19
To: perl-win32-gui-users@lists.sourceforge.net
Subject: [perl-win32-gui-users] Setting individual item properties


Awhile back someone was asking about changing the color of individual
items 
in a ListView control.  It can be done if someone knows if there is a
way 
to set the properties of the items.

What needs to be done is set the item's UseItemStyleForSubItems property
to 
false but am not sure if it can be done using the Win32::GUI module.

Is it possible?  If so, how?

An example where this is used is in Windows 2000 (and maybe XP) when you

have Show All Files enabled and none of the system folders are hidden.
The 
protected system folders are in blue but the rest of the list is black.

Anyway I have a need for this now and was wondering if anyone knows if
the 
properties thing can be done.


Jonathan
========================
Jonathan Southwick
[EMAIL PROTECTED]
Technical & Network Services
Allegheny College
Meadville, PA 16335
(814) 332-2755



-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
Perl-Win32-GUI-Users mailing list
Perl-Win32-GUI-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users



-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
Perl-Win32-GUI-Users mailing list
Perl-Win32-GUI-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users



Reply via email to