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