|
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/
>>>
>>
>>
|