From: Octavian R. <ora...@gm...> - 2010-08-28 13:27:15
|
Hi Kevin, I was asking this because all the standard controls which can be created with Win32::GUI are accessible without doing anything special. Octavian ----- Original Message ----- From: "Kevin Marshall" <kej...@ho...> To: "Octavian Rasnita" <ora...@gm...> Cc: <per...@li...> Sent: Saturday, August 28, 2010 1:56 PM Subject: Re: [perl-win32-gui-users] Win32::GUI Owner Drawn Controls > Hi Octavian, > > Thanks for your comments. It's good to know that you find it useful. > > I have been looking into Windows Accessibility to see how it works, and > it seems that under normal circumstances (i.e. creating GUIs using C++, > rather than Perl), the custom controls must provide an interface to the > Accessibility API, which accessibility programs can use to interact with > the control. Unfortunately, it looks like it is probably beyond the > scope of the Win32::GUI module. > > Perhaps it is something that could be looked into for a separate module. > > Other people may have thoughts on the topic. > > Thanks again, > > Kevin. > >> Hi Kevin, >> >> Congratulations for the program! >> >> I have tested it with a screen reader and it works. I added the -dialogui => 1 option to the $winMain object to be able to use the keyboard for changing the focus. >> >> The only problem, which is an important one, is that if I arrow up or down in the list box, the screen reader announces just things like "item 1 of 8, item 2 of 8" and so on, without telling the label of the current item as it should. >> >> Do you (or somebody else) have any idea how to add accessibility features (MSAA) to this custom control in order to be as useful as a standard control? >> >> Basicly it should also report the labels of the list box items and not just print them. >> >> Thank you. >> >> Octavian >> >> ----- Original Message ----- >> From: "Kevin Marshall"<kej...@ho...> >> To:<per...@li...> >> Sent: Saturday, August 28, 2010 8:07 AM >> Subject: [perl-win32-gui-users] Win32::GUI Owner Drawn Controls >> >> >> >>> Hi everyone, >>> >>> After much experimentation, I have finally succeeded in creating an >>> owner-drawn control in Win32::GUI. I decided to create this post >>> detailing how to create an owner-drawn control in case someone else has >>> the need to use one. >>> >>> For those of you who don't know, an owner-drawn control allows the user >>> more control over the appearance of the control. This usually involves >>> responding to messages sent whenever the control needs to be drawn and >>> drawing the control in anyway that you wish. >>> >>> In order to get my sample to work you will need to install the PeekPoke >>> module from CPAN. This module allows reading and writing of data to and >>> from arbitrary memory locations. This is needed to set the height of the >>> items of the listbox. More on this below. >>> >>> This example was created using ActiveState Perl v5.12.0 running on >>> Windows XP. >>> >>> For this example, I will demonstrate how to create an owner-drawn >>> listbox. The listbox will have items with a larger height, will display >>> two lines of text with different formats, and an image. >>> >>> All of the files related to this example at the bottom of this post. >>> >>> Anyway, on with the example. >>> >>> I decided to store the information about each listbox item in an >>> external XML file and use XML::Simple to parse it. This makes it rather >>> simple to change the information for the listbox items. >>> >>> I also created 8 simple 40x40 bitmaps that will be displayed in each >>> listbox item. >>> >>> Now for a description of the code. >>> >>> The first step is to create a window for our listbox and load our XML >>> data from the file using XML::Simple::XMLin(). This is all fairly >>> simple, so I won't bother explaining. >>> >>> Next step is to create a hook for the WM_MEASUREITEM message. This >>> message is sent when the listbox is created so the user can specify the >>> width and height of the listbox items. The $lParam variable contains the >>> address of the structure that is passed to the message, which needs to >>> be filled out. Here we use the poke() function to write the desired >>> height into the structure, which in our case is 50. 16 is the offset of >>> the itemHeight member of the structure which needs to contain the height >>> that we want when the message returns. >>> >>> Next a hook is created for the WM_DRAWITEM message. This message is sent >>> whenever an item in the listbox requires drawing. First step is to >>> unpack the structure that is passed to the message. If the itemID >>> contains -1, then the listbox is empty, so we simply return from the sub >>> if this occurs. Otherwise, it contains the zero-based index of the item >>> being drawn. The itemAction member contains the action required for the >>> drawing. Here we respond if the entire item needs drawing. To begin with >>> we draw the bitmap for the item. First we create a compatible DC from >>> the DC that is passed to the message, then select the bitmap for the >>> current item into it. Then we BitBlt() the contents of the compatible DC >>> into the item DC. Next we need to draw the text that will be displayed >>> in the item. We create a large font that will be used for the item's >>> heading, and select the font into the item DC, remembering the old font. >>> Then we draw the text into the item DC using DrawText(). Next we select >>> the old font, and draw the other text that will be displayed in the >>> item. That completes the drawing for the item, so we return from our sub. >>> >>> Next step is to create our listbox. The only difference here from >>> creating an ordinary listbox is to specify the LBS_OWNERDRAWFIXED style. >>> This specifies that the listbox will be owner-drawn, and all the items >>> have the same height. An alternative would be to use the >>> LBS_OWNERDRAWVARIABLE style instead, which specifies that each item will >>> have a different height. In this case, the WM_MEASUREITEM would be sent >>> for each item when the control is created, not just once like our case. >>> >>> Next we loop through each item returned from the XML file, create a >>> Win32::GUI::Bitmap from the file name specified in the file, and add the >>> relevant data to an array which will be used when drawing the listbox >>> items. We also add an item to the listbox using the text as a place >>> holder, although it won't get drawn, so it doesn't matter what is >>> inserted here. Then we simply show the window and enter the dialog phase. >>> >>> The listbox acts like any other listbox, it just has larger items and >>> different content. This is demonstrated here when an item is selected: >>> the heading and text of the selected item are printed. >>> >>> That's it for creating an owner-drawn listbox. >>> >>> Various other controls can also be owner-draw, such as buttons, labels, >>> and combo boxes. I have yet to try it with other controls, but it >>> shouldn't be much different from a listbox. >>> >>> More information about owner-draw controls can be found in the Windows >>> SDK Documentation. >>> >>> I hope that someone finds this example useful. If you come up with >>> something interesting, I wouldn't mind a reply post detailing what you >>> have done. >>> >>> Kevin. >>> >>> Here are the files: >>> >>> This is the main code: >>> >>> #!perl >>> ################################################################################ >>> # >>> # customlistbox.pl >>> # >>> # Win32::GUI Owner-drawn Controls >>> # >>> # This script demonstrates the creation and use of an owner-drawn listbox. >>> # >>> # Requirements: >>> # Win32::GUI >>> # PeekPoke >>> # XML::Simple >>> # >>> # This program was written using ActiveState Perl 5.12.0 Build 1200 >>> running on >>> # Windows XP and using Win32::GUI v1.06, PeekPoke v0.01, and >>> XML::Simple v2.18 >>> # >>> ################################################################################ >>> use strict; >>> use warnings; >>> >>> use PeekPoke qw(poke); >>> use Win32::GUI qw(); >>> use Win32::GUI::Constants qw(CW_USEDEFAULT WM_MEASUREITEM WM_DRAWITEM >>> ODA_DRAWENTIRE SRCCOPY DT_LEFT DT_TOP DT_WORDBREAK LBS_OWNERDRAWFIXED); >>> use XML::Simple; >>> >>> # Create our main window >>> my $winMain = Win32::GUI::Window->new( >>> -name => 'winMain', >>> -text => 'Owner-Drawn Listbox', >>> -size => [ 320, 240 ], >>> -minwidth => 320, >>> -minheight => 240, >>> ); >>> >>> # Load XML data >>> my $ListBoxItems = XMLin('customlistbox.xml'); >>> my @Items; >>> >>> # Create a hook to handle WM_MEASUREITEM message. This message is used >>> to set the >>> # height of the listbox items. >>> $winMain->Hook( >>> WM_MEASUREITEM, >>> sub { >>> my( $self, $wParam, $lParam, $type, $msgcode ) = @_; >>> return 1 unless $type == 0; >>> return 1 unless $msgcode == WM_MEASUREITEM; >>> # Write desired height of items to structure. 16 is the offset >>> of the >>> # itemHeight member of the MEASUREITEMSTRUCT structure >>> poke( $lParam + 16, 50 ); >>> return 1; >>> }, >>> ); >>> >>> # Create a hook to handle the WM_DRAWITEM message. This message is sent >>> whenever >>> # a listbox item needs drawing >>> $winMain->Hook( >>> WM_DRAWITEM, >>> sub { >>> my( $self, $wParam, $lParam, $type, $msgcode ) = @_; >>> my %drawitem; >>> # Unpack data from the structure >>> @drawitem{qw(CtlType CtlID itemID itemAction itemState hwndItem >>> hDC left >>> top right bottom itemData)} = unpack 'IIIIILLllllL', unpack >>> 'P48', >>> pack 'L', $lParam; >>> # itemID will contain -1 if there are no items, so we just return >>> return 1 if $drawitem{'itemID'} == -1; >>> >>> # Draw the bitmap and text for the list box item. >>> if( $drawitem{'itemAction'} == ODA_DRAWENTIRE ){ >>> my $hDC = $drawitem{'hDC'}; >>> >>> # Display the bitmap associated with the item. >>> my $image = $Items[ $drawitem{'itemID'} ]{'image'}; >>> my $memdc = Win32::GUI::DC::CreateCompatibleDC($hDC); >>> my $oldimage = $memdc->SelectObject($image); >>> Win32::GUI::DC::BitBlt( >>> $hDC, $drawitem{'right'} - 45, $drawitem{'top'} + 5, >>> 40, 40, $memdc, 0, 0, SRCCOPY >>> ); >>> >>> # Display the text associated with the item. >>> my $titlefont = Win32::GUI::Font->new( >>> -height => 12, >>> -weight => 700, >>> ); >>> my $oldfont = Win32::GUI::DC::SelectObject( $hDC, $titlefont ); >>> Win32::GUI::DC::DrawText( >>> $hDC, >>> $Items[ $drawitem{'itemID'} ]{'heading'}, >>> $drawitem{'left'} + 5, $drawitem{'top'} + 5, >>> $drawitem{'right'} - 50, $drawitem{'bottom'} - 5, >>> ); >>> Win32::GUI::DC::SelectObject($drawitem{'hDC'}, $oldfont); >>> Win32::GUI::DC::DrawText( >>> $hDC, >>> $Items[ $drawitem{'itemID'} ]{'text'}, >>> $drawitem{'left'} + 5, $drawitem{'top'} + 30, >>> $drawitem{'right'} - 50, $drawitem{'bottom'} - 5, >>> DT_LEFT | DT_TOP | DT_WORDBREAK >>> ); >>> } >>> return 1; >>> } >>> ); >>> >>> # Create our listbox control >>> my $lsbCustom = $winMain->AddListbox( >>> -name => 'lsbCustom', >>> -pos => [ 10, 10 ], >>> -size => [ $winMain->ScaleWidth() - 20, >>> $winMain->ScaleHeight() - 20 ], >>> -nointegralheight => 1, >>> -vscroll => 1, >>> -pushstyle => LBS_OWNERDRAWFIXED, >>> ); >>> # Add items to listbox >>> foreach my $item ( @{ $ListBoxItems->{'item'} } ){ >>> my $bmp = Win32::GUI::Bitmap->new( $item->{'image'} ); >>> push @Items, { >>> heading => $item->{'heading'}, >>> text => $item->{'text'}, >>> image => $bmp, >>> }; >>> $lsbCustom->InsertString( $item->{text} ); >>> } >>> >>> $winMain->Show(); >>> >>> Win32::GUI::Dialog(); >>> >>> sub winMain_Terminate { >>> return -1; >>> } >>> >>> sub winMain_Resize { >>> my $width = $winMain->ScaleWidth(); >>> my $height = $winMain->ScaleHeight(); >>> $lsbCustom->Resize( $width - 20, $height - 20 ); >>> return 1; >>> } >>> >>> sub lsbCustom_SelChange { >>> my $index = $lsbCustom->GetCurSel(); >>> print<<EOT; >>> $Items[$index]{heading} >>> $Items[$index]{text} >>> EOT >>> return 1; >>> } >>> >>> __END__ # of customlistbox.pl >>> >>> >>> >>> This is the XML file that stores the data for each item in the listbox: >>> >>> <!-- customlistbox.xml --> >>> <listboxitems> >>> <item> >>> <heading>Item 1</heading> >>> <image>item1.bmp</image> >>> <text>This is some text for item 1</text> >>> </item> >>> <item> >>> <heading>Item 2</heading> >>> <image>item2.bmp</image> >>> <text>This is some text for item 2</text> >>> </item> >>> <item> >>> <heading>Item 3</heading> >>> <image>item3.bmp</image> >>> <text>This is some text for item 3</text> >>> </item> >>> <item> >>> <heading>Item 4</heading> >>> <image>item4.bmp</image> >>> <text>This is some text for item 4</text> >>> </item> >>> <item> >>> <heading>Item 5</heading> >>> <image>item5.bmp</image> >>> <text>This is some text for item 5</text> >>> </item> >>> <item> >>> <heading>Item 6</heading> >>> <image>item6.bmp</image> >>> <text>This is some text for item 6</text> >>> </item> >>> <item> >>> <heading>Item 7</heading> >>> <image>item7.bmp</image> >>> <text>This is some text for item 7</text> >>> </item> >>> <item> >>> <heading>Item 8</heading> >>> <image>item8.bmp</image> >>> <text>This is some text for item 8</text> >>> </item> >>> </listboxitems> >>> <!-- end of customlistbox.xml --> >>> >>> If you execute this script, it will create a file called pics.7z file, >>> which will contain the 8 bitmaps needed for this sample: >>> >>> #!perl >>> use strict; >>> use warnings; >>> >>> use MIME::Base64; >>> >>> open my $fh, '>', 'pics.7z' or die $!; >>> binmode $fh; >>> print {$fh} MIME::Base64::decode( >>> 'N3q8ryccAANPwVVtOwEAAAAAAAAjAAAAAAAAAJASfkEAIRNayxcGoME2nyL7I4JzfZi4oHYg66A8 >>> nm6WsRvMHTne+oX2PHIJM7ayDfdnbZ0DmCN8Mf70re7XhMyBeX4+OafcrXhvLiG669M+EMuzgnG7 >>> JvuHqsUDJQokFWg0SzmcesrNrAHXMApzksKeghHSU1HMZ64/6cXUSTzQaCJdREH7ieEAAACBMweu >>> D9Uvw85WbCkfSCtBMmjGwE0B4XqeDwoyHBt1/T8r3bH8o1BWWPseZbEvATR9EeL4s4UpAsX59y9L >>> RF7bndv+H7Dz0pCHk43K2555nX5iAiwmibuV8uDOx83QgHHTqy9AORcPkqPfO6duMlkZ+UYo1t0/ >>> TapX+1Jl1LSaAcpSost05OeRFdSSTWGt3tvzEPzEG8sIrZ+vTlWBzDSQrvvsJkdLC0r63jRJhP2+ >>> sK6GAAAXBoCFAQmAtgAHCwEAASMDAQEFXQAQAAAMgWMKAVQcA6kAAA=='); >>> close $fh; >>> >>> __END__ >>> >>> >>> >>> >>> ------------------------------------------------------------------------------ >>> Sell apps to millions through the Intel(R) Atom(Tm) Developer Program >>> Be part of this innovative community and reach millions of netbook users >>> worldwide. Take advantage of special opportunities to increase revenue and >>> speed time-to-market. Join now, and jumpstart your future. >>> http://p.sf.net/sfu/intel-atom-d2d >>> _______________________________________________ >>> Perl-Win32-GUI-Users mailing list >>> Per...@li... >>> https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users >>> http://perl-win32-gui.sourceforge.net/ >>> >> >> |