From: Kevin M. <kej...@ho...> - 2010-08-29 13:07:59
|
Octavian, According to the Windows docs, the common controls are automatically accessible, which are what Win32::GUI uses, whereas custom controls require additional setup. Kevin. > 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/ >>>> >>>> >>> >>> > > |