TBZ Toolbar buttons for Visual FoxPro | Home |
This class provides controls that can be used as toolbar controls without having to create an actual VFP toolbar. Just drag and drop the desired controls into the form, move them to the top/bottom of the form, add a line control to simulate a toolbar border, and you are done. DOWNLOAD Updated 2014-05-26-15-30 Google groups forum
UPDATES
tbtimer event added. tbpicturecolorkey and tbmenupicturecolorkey added. tbmenupicturesize added. classes _tbzutil and _tbzcontextmenu merged with _tb main class.Adde code to parse ico files to overcome gdiplus bugs. - Now all PicturePosition values are supported. - Property tbPictureAlpha added, now the transparency level of the button picture can be adjusted from 0 to 255: - After being bitten again by other tools that declare dlls and mess with the existing declared functions, all the declare dll statements are moved to individual prgs to protect them from any tampering. This is how my classes are designed anyway, I just merge all the API declare prgs into one method inside the class just so you donīt have to deal with 70+ prg files. Well, not anymore, now the API declares will be in individual prg files. So, now the download will be the class files, all with a "_tbz" prefix and a bunch of prg files with an "_api" prefix. The api prg files can be moved anywhere where VFP will find them. - Multi-line captions are now possible. Separate lines in caption property with "|" - Now the left and right part of splitbuttons react independently to HOT and PRESSED states. Support for layout has been added, using the Alignment and PicturePosition properties. Dropdown menu added. - All of the logic to determine control state that was in the generatebitmap method has been moved to the uiupdate method. An array property is now used to store uistate properties used by generatebitmap to speed up creation of state bitmaps. The control UI state logic has been cleaned up, check _tbz.xls for list of states. It's still kind of messy because we are handling many types of controls within the same code. Maybe in the future with a more mature code base, all the logic can be split into each control class. The format of the png style files has been changed, see specs at the bottom. See _tbz.txt for list of changes. I always wanted an easy way to create a toolbar for my forms, and the process of actually creating one in Visual FoxPro, at least in my opinion, is complicated and cumbersome. This is why I created these controls, that can be used easily in any kind of form. The main property of these controls is than they cannot get focus, so they never steal focus away from the current focused control, just like any toobar button should do. The included controls are: tbcheck: equivalent to a checkbox control tbcommand: equivalent to a commandbutton control tbdropdown: no equivalent in VFP tbline: just a simple subclassed line control that is used to simulate the "toolbar" border. tbradio: equivalent to an optionbutton control. This maybe should not be used in a toolbar, but it was easy to create, since it is almost the same thing as the tbcheck control. tbsplitbutton: no equivalent in VFP. A button with two parts where you can click the left part of the control, or the right dropdown part. tbtoggle: equivalent to a checkbox control with style set to 1 - Graphical Dropdown menu class included to easily build drop down menus on the fly: The visual aspect of the controls can be easily customized by creating an image file with the states of the controls. A number of styles are already included: 1. Classic Windows style 2. Chrome style 3. Firefox Aurora style 4. Internet Explorer style 5. Windows 7 Explorer toolbar style 6. Windows 7 Explorer toolbar style with toolbar background 7. Windows 8 style 8. Flat style The checkbox and radio button controls derive their look from the operating system, so they always match:
How do PicturePosition and Alignment work
The control uses the PicturePosition to determine the relative position of the picture and the caption. Possible values are 0 to 14:The value of PicturePosition affects the rectangle available for the caption. The yellow rectangles indicate the area available for the caption for each value of PicturePosition. Once PicturePosition is defined, the value of Alignment determines the position of the caption INSIDE the caption rectangle (the yellow rectangle in the images). For example, for PicturePosition 0, these are the possible values of Alignment: This is not how the original commandbutton works, but handling this way PicturePosition and Alignment seems more practical. PicturePosition 7 and 13 are the same.
Quick how to use
Add the _tbz.vcx file to your project, drag and drop the controls from the project manager to a form, arrange the controls against the top border of the form, change captions, optionally add pictures, add code to the click event of the controls, you are done.
Properties, Events and Methods
The class is based in the VFP commandbutton class, and some of the parent class properties are used:
Alignment
Caption
FontBold, FontItalic, FontName, FontSize, etc
Forecolor
DropDownClick
Event.Fired when the user clicks the right part of a splitbutton control Remarks: Usually the code in this event should display a dropdown menu. The dropdown menu generation code is not implemented yet, I use a separate class for generic context menus for this, that I will integrate some day into this classes.
Picture
Specifies the picture displayed in the control. There is no need to specify additional pictures, the downpicture and disabled pictured are automatically created from this picture. Actually, three aditional pictures are created, one each for HOT, PRESSED and DISABLED states. The HOT state picture is slightly brighter, the PRESSED picture is a bit darker, and the disabled picture uses the same color matrix used by the Net Framework to create disabled pictures.The picture specified can be any format or size, the class converts, resizes, and applies transparency as needed. Pictures do not have to be of a certain size to be used as a control picture. The control can automagically adjust the picture size. The picture file format can be any type supported by GDI+ : BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF. For formats that do not have transparency, like bmp, the control assumes the color of the top left pixel of the image should be made transparent. gets resized like this:
PicturePosition
All values 0 to 14 are supported.In this example, we have some toggle controls, with tbautowidth = .F., tbPictureAutoSize = .F., tbStyle = 7, tbValue = .T. The mouse is over the last control. This is how this form looks like in design mode: Here the only change between controls is the PicturePosition property, tbautowidth = .T., tbPictureAutoSize = .T.
PictureVal
Property.Value Type: String Default Value: NONE R/W: Read/Write. Like the PictureVal property of image controls
ToolTipText
The control implements native API tooltips, so they will display with the look determined by the operating system version.
tbAlign
Property.Value Type: Numeric. Default Value: 1 R/W: Read/Write. Specifies the alignment of the control relative to the parent control or form. Possible values are: 0 = No alignment 1 = Left aligned 2 = Right aligned Remarks: When tbAlign is 0, the control is not moved in the INIT event of the form. When tbAlign is 1, the control is aligned to the left side of the form in the INIT event of the form. The leftmost control will have a margin from the left form border equal to the value of the tbMarginH property. The spacing between controls is determined by the value of the tbMargin property. When tbAlign is 2, the control is aligned to the right side of the form in the INIT event of the form. The rightmost control will have a margin from the right form border equal to the value of the tbMarginH property. The spacing between controls is determined by the value of the tbMargin property. When tbAlign is either 1 or 2, the controls are also aligned to the top/bottom of the form, with a margin from the form top/bottom border equal to the value of the tbMarginV property, but only if they are near the form top/bottom border by a value equal or less than tbMarginV. How it works: During the control INIT, a BINDEVENT to the form INIT is established, to the control _ARRANGECONTROLS method. This method searches the form for controls with the same TOP value, with the same tbAlign value, and determines if the control is the leftmost/rightmost control of the group. If the control is the leftmost/rightmost control, it moves itself to the left/right border of the form, and then moves each control of the group in sequence, taking into account each individual control width and tbMargin.
tbAutoColor
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the control changes its color to match the color of the parent BACKGROUND. Remarks: The image png that determines the control style may have some general color hue that has to be changed to match the background of the control. For some styles, this is not desired. Some styles have transparent or semitransparent pixels that should be applied as is, without changing its colors. The class uses the value of the top left pixel of the style png to determine if the color should really be changed when tbAutoColor is TRUE. if this pixel is black with a 100% transparency, the colors are not changed. How it works: The colors of the style png are changed using GDIPLUS by aplying a color matrix transformation to the bitmap.
tbAutoFontName
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the control uses the default font name of the system for the control caption, or the font specified in the FontName property. Remarks: Different versions of Windows use different fonts for the user interface, for example Windows 7 uses SEGOE UI 9pt, Windows XP uses TAHOMA 8pt. When this property is TRUE, the default system font is used, instead of the font specified in the property FontName. How it works: When set to TRUE, a call to SystemParametersInfo is used to obtain a NONCLIENTMETRICS structure that includes an lfMessageFont LOGFONT structure of the font used in message boxes. This structure is used to create the font used in the control. When set to FALSE, a LOGFONT structure is created with the values of the control Font related properties.
tbAutoFontSize
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the control uses the default font size of the system for the control caption, or the font size specified en the FontSize property. Remarks: This property is only used when tbAutoFontName is TRUE. If tbAutoFontName is FALSE, then this property has no effect. Different versions of Windows use different fonts for the user interface, for example Windows 7 uses SEGOE UI 9pt , Windows XP uses TAHOMA 8pt. When this property is TRUE, the default system font size is used, instead of the font size specified in the property FontSize. How it works: When tbAutoFontName is TRUE and this property is FALSE, a call to SystemParametersInfo is used to obtain a NONCLIENTMETRICS structure that includes a lfMessageFont LOGFONT structure of the font used in message boxes. The value of lfHeight in the structure is updated with the value of the FontSize property and then this structure is used to create the font used in the control. This property was implemented because I prefer to use the system default fonts, but with an 8 pt size instead of the 9pt default value of Windows 7.
tbAutoWidth
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the control width is adjusted in relation to the width of the caption property. Remarks: This property only has effect when the control is instantiated, subsequent changes of the caption text have no effect in the control width.
tbBmpBottom, tbBmpLeft, tbBmpRight, tbBmpTop
Property.Value Type: Numeric. Default Value: 4,4,4,4 R/W: Read/Write. Specifies the bitmap margins when creating the control background bitmap. Remarks: No reason to change these values unless you implement custom styles pngs that require it. To see how these are used, see the _generatebitmap method of the class. http://www.codeproject.com/Articles/674559/Drawing-Images-with-Sizing-Paddings
tbCaptionMargin
Property.Value Type: Numeric. Default Value: 5 R/W: Read/Write. Specifies the margin between the control caption and the borders of the control, in pixels. Remarks: When a control has a picture and a caption, the margin between the picture and the caption is specified in tbPictureCaptionMargin, the margin for the picture in tbPictureMargin, and the margin for the caption in tbCaptionMargin.
tbCaptionMarginV
Property.Value Type: Numeric. Default Value: 5 R/W: Read/Write. Specifies the vertical margin between the control caption and the borders of the control, in pixels. Remarks: When a control has a picture and a caption, the margin between the picture and the caption is specified in tbPictureCaptionMargin, the margin for the picture in tbPictureMargin, and the margin for the caption in tbCaptionMargin.
tbClass
Property.Value Type: Numeric. Default Value: the value for each class. R/W: Read only Specifies the subclass of the control. Remarks: All the controls are subclasses of the tb control, an abstract class that should not be used directly. This property determines the type of control subclassed. This way all the logic is kept in the main parent class and the subclasses only change this property and a limited number of other properties, and have no code in them. when the code becomes stable, the specific code for each class will be moved to the subclasses.
tbDestroy
Event.User code for the destroy event of the control goes here. Remarks: Use this event instead of the Destroy event of the control for you own code. This method is called before the destroy event class code.
tbDropDownWidth
Property.Value Type: Numeric. Default Value: 0 R/W: Read only Specifies the width of the arrow area of a dropdown control Remarks: When 0, the width is calculated proportional to the control height.
tbEnableCheckHot
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the checkbox control should be highlighted when the mouse is over it. Remarks: Set this to FALSE to follow Windows behaviour for checkbox controls, only the checkbox gets highlighted.
tbEnableRadioHot
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the radio control should be highlighted when the mouse is over it. Remarks: Set this to FALSE to follow Windows behaviour for radio controls, only the checkbox gets highlighted.
tbFocusable
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the control can get focus. Remarks: The logic for this is not yet implemented, the idea is to be able to use these controls as replacement of the VFP stock controls. Since I have no need for this, it is not done.
tbgdipinterpolationmode
Property.Value Type: Numeric. Default Value: 7 R/W: Read/Write. Specifies the interpolation mode used by gdiplus to draw the control picture into the bitmap Remarks: Needs experimenting to determine best value. Possible values are:
tbgdipsmoothingmode
Property.Value Type: Numeric. Default Value: 3 R/W: Read/Write. Specifies the smoothing mode used by gdiplus to draw the control picture into the bitmap Remarks: Needs experimenting to determine best value. Possible values are:
tbGroupId
Property.Value Type: Numeric. Default Value: 0 R/W: Read/Write. Specifies the group ID of the control. Remarks: Used by tbradio or tbtoggle class controls. Radio controls with the same tbGroupId value change their value when one of the controls in the group changes value. tbtoggle controls with a tbgroupid # 0 also act this way.
tbInit
Event.User code for the init event of the control goes here. Remarks: Use this event instead of the init event of the control for you own code. This method is called before the init event class code.
tbMargin
Property.Value Type: Numeric. Default Value: 1 R/W: Read/Write. Specifies the margin between the control and the control to the left/right of it depending on the value of the tbAlign property of the controls. Remarks: Using this property, there is no need to have invisible separators between the controls, just set the property to have a wider margin to the left/right side of the control.
tbMarginH
Property.Value Type: Numeric. Default Value: 12 R/W: Read/Write. Specifies the margin between the leftmost/rightmost control and the left/right border of the form, depending on the value of the tbAlign property of the control. Remarks: If the control tbAlign property is 1 and this is the leftmost control, this specifies the margin between the control and the left border of the form.
tbMarginV
Property.Value Type: Numeric. Default Value: 2 R/W: Read/Write. Specifies the margin between the top/bottom of the form and the top/bottom of the control. Remarks: This property is used only when tbAlign is 1 or 2, and the control is within this value of the top/bottom border of the form. Useful for not having to exactly vertically align the controls, just position them flush with the form top/bottom border.
tbMenuItemAdd
Method.Use this method to add menu items to the built-in dropdown menu control. Parameters: pItemID, pParentId, pItemType, pItemChecked, pItemDisabled, pItemCaption, pItemPicture pItemdID: a numeric value that acts as an ID fot the menu item. When calling tbMenuShow and the user clicks on a menu item this will be the return value of the method. pParentID: The numeric ID of the parent menu of the menu item. The default value is 0. If you add a submenu, it will be the ItemId of the menu item that corresponds to that submenu. pItemType: the kind of menu item to add 0: a normal menuitem 1: a separator 2: a radio button will be used as checkmark of the menuitem 3: the menuitem will open a submenu pItemChecked: default value 0. If 1, the menuitem will have a check mark or a radio mark if pItemType is 2 pItemDisabled: defaut value 0. If 1, the menuitem will be disabled. pItemCaption: the caption of the menuitem pItemPicture: the picture of the menuitem. It can be any type that gdiplus accepts, and any size. Remarks: The dropdown menu created exists only while it is shown, you have to add menuitems every time you want to call tbmenushow. You will usually do this in the Click or DropDownClick events of the control. Example: This.tbmenuitemadd(1,0,0,0,0,'TEST',"C:\VFPPA\IMAGES\agt_business.png") This.tbmenuitemadd(2,0,0,0,1,'TEST',"C:\VFPPA\IMAGES\agt_desktop_enhancements.png") This.tbmenuitemadd(3,0,0,0,0,'TEST',"C:\VFPPA\IMAGES\agt_games.png") ?This.tbmenuShow()
tbMenuPictureSize
Property.Value Type: Numeric. Default Value: 16 R/W: Read/Write. Specifies size of the menuitem pictures in pixels. Remarks: 16 pixels if a nice value, no need to change it.
tbMenuShow
Method.Use this method to display a context menu built using tbMenuItemAdd commands. The return value is the ItemId of the menu clicked, or 0 if no menuitem was selected. Parameters: None If the control is left aligned, the menu will be left aligned and the origin will be the bottom left corner of the control if the control is right aligned, the menu eill be right aligned and the origin will be the bottom right corner of the control.
tbPictureAlpha
Property.Value Type: Numeric. Default Value: 255 R/W: Read/Write. Range 0 to 255. Specifies the transparency level of the picture. 255 is fully opaque, 0 is fully transparent
tbPictureAutosize
Property.Value Type: Logical. Default Value: .T. R/W: Read/Write. Specifies if the picture size should be adjusted to fit in the control, considering the control height and the value of the tbPictureMargin property. Remarks: When set the FALSE, the picture size is specified by the tbPictureSize property.
tbPictureColorKey
Property.Value Type: Numeric. Default Value: -1 R/W: Read/Write. Specifies the color to make transparent for bmp and gif images Remarks: When this property is -1, the top left pixel of the image is used as transparent color. Specify a color to make transparent for bmp and gif files.
tbPictureSize
Property.Value Type: Numeric. Default Value: 16 R/W: Read/Write. Specifies size of the picture in pixels, only when tbPictureAutosize is FALSE Remarks: When tbPictureAutosize is TRUE, the control height and the value of tbPictureMargin determine the size of the picture. This is useful if you want the control pictures to appear a certain fixed size, maybe for example when creating picture only toolbar buttons. For buttons with only a picture and no caption, the control width is set to the control height, so it will be exaclty square, if tbAutosize is TRUE.
tbSplitTop
Property.Value Type: Numeric. Default Value: 0 R/W: Read/Write. Specifies the height of the top part of a vertical split button control Remarks: When 0, it will be calculated automatically.
tbSplitWidth
Property.Value Type: Numeric. Default Value: 0 R/W: Read/Write. Specifies the width of the right part of a split button control Remarks: When 0, the width is calculated proportional to the control height.
tbStyle
Property.Value Type: Numeric. Default Value: 2 R/W: Read/Write. Specifies the style of the control. Remarks: The control style is determined by the png file use for the control parts. Included are eight png files for eight styles: _tbz01.png to _tbz08.png These files are added to your project by INCLUDE statements in the class INIT. The png files can be modifed, or new ones created to produce more styles, see below for the file format.
tbTimer
Event.User code for the timer event of the control goes here. Remarks: The control has a timer that fires every 100 ms and is used to show/hide the tooltip. Use this event to make use of this timer.
tbValue
Property.Value Type: Logical Default Value: .F. R/W: Read/Write. Specifies the Value of the control. Remarks: Used by checkbox and radio controls, equivalent to the VFP Value property. (A property named VALUE cannot be added to the class, because it throws and error when reopening the class for editing)
How it works
The main base class is _tb, all the other controls are derived from this class. Behaviour of each class is determined by the value of the tbClass property:#Define TBZ_COMMAND 0 #Define TBZ_TOGGLE 1 #Define TBZ_CHECK 2 #Define TBZ_WHOLEDROPDOWN 3 #Define TBZ_DROPDOWN 4 #Define TBZ_RADIO 5 All the logic is contained in the _tb class, the child classes only change the value of the tbClass property. So basically we have a subclassed commandbutton control. In the INIT the _DECLARES method is called, where we declare all the API functions used by the class. In case of an unintentional CLEAR DLLS, there is a try-catch to detect it and reddclare the API functions. Next, a _tbz object is added to the parent of the control, and a reference to this object is stored in _octrl. The original control will be hidden out of the way and this surrogate object will serve as a dumb user interface object controlled by the original object. What the control does basically is determine user interface changes by code in MOUSEMOVE, MOUSEDOWN, MOUSEUP, etc. and everytime the visual state of the control has to be changed the _UIUPDATE method is called. Inside this method, we determine the correct UI state of the control (NORMAL, HOT, PRESSED, DISABLED...) and just assign the cached bitmap for the state to the image inside the _tbz object (the only visible control to the user) If there is no bitmap for that state, _UIUPDATE calls _GENERATEBITMAP, a method that generates the bitmap for the specified control state and parameters (caption, picture, font, class, etc) Most of the action happens in the _GENERATEBITMAP method, using GDIPLUS and GDI, the THEMES API, and others. The checkbox and the radio button are painted using native API calls, in themed and unthemed versions, so they will always match the style of the Windows version being used. The tooltip is controlled by a timer control, with an interval set to the system double click time * 2. This timer is enabled when the mouse is over the control, and disabled when the mouse moves out of the control. If the mouse stays over the control long enough, the timer will display the tooltip, change its interval to double click time * 10 and when fired again will hide the tooltip and disable itself. Over the visible image control that the user sees there are two transparent shapes that control mouse interaction and clicks. The left/top one handles normal control clicks, the right/bottom one handles clicks in the dropdown area of the splitbutton and fires the DropDownClick event.
Specifications of the png style files
UPDATED 2014-05-18WARNING: IF YOU EDIT THE PNG STYLE FILES, BE AWARE THAT THE CLASS CACHES THE BITMAPS IN A SCREEN PROPERTY. EITHER RESTART VFP OR SET _SCREEN.tbz_cachepictureval TO false to clear the PNG files cache. I mention this because I spent 45 minutes wondering why I was getting errors after doing some changes, and it was because of this. The control parts are stored in the png style files in this way: (actual size) There are 4 columns and 7 rows. Each control part is 30 pixels wide by 26 pixels tall, each control part represents a control state. The arrows in the last row are 15 pixels wide. Like the VFP commandbuttons, the parts have a one pixel wide border margin. ROW 1 is for all controls except the ones that are of type split. The parts from left to right are NORMAL, HOT, PRESSED and DISABLED states. ROW 2 is for TOGGLED buttons: NORMAL, HOT, PRESSED and DISABLED states. The hot state of a toggled button is the same as the hot state for an untoggled button. I do not like this, but is the way MS does it. I would prefer to have all 4 states of a toggled button just toggled. ROW 3 is for horizontal splitbuttons, NORMAL, HOTL, PRESSEDL, DISABLED. This are states for the left part of the split ROW 4 is for horizontal splitbuttons, NORMAL, HOTR, PRESSEDR, DISABLED. This are states for the right part of the split. (NORMAL and DISABLED are redundant) ROW 5 is for vertical splitbuttons, NORMAL, HOTL, PRESSEDL, DISABLED. This are states for the left part of the split ROW 6 is for vertical splitbuttons, NORMAL, HOTR, PRESSEDR, DISABLED. This are states for the right part of the split. (NORMAL and DISABLED are redundant) ROW 7 are the arrows for dropdown and splitbutton, in NORMAL, HOT, PRESSED and DISABLED states. Some part states are the same, like the TOGGLE type parts, or the normal and disabled states, because this way the most liberty to change individual styles is possible. A Paint Shop Pro file is included in the zip as a template, _tbz00.pspimage.
References
http://www.jose.it-berater.org/gdiplus/iframe/index.htmhttp://support.microsoft.com/kb/867631 http://theartofdev.wordpress.com/2013/08/12/using-native-gdi-for-text-rendering-in-c/ https://gist.github.com/ArthurHub/10527752 http://stackoverflow.com/questions/849531/textrenderer-drawtext-in-bitmap-vs-onpaintbackground http://www.codeproject.com/Articles/674559/Drawing-Images-with-Sizing-Paddings http://www.codeproject.com/Tips/66909/Rendering-fast-with-GDI-What-to-do-and-what-not-to
Miscellaneous Ramblings
At first I tried to use the excellent gdiplusx class for processing the images, but it was too slow, so I just switched to use the gdi+ API directly.The control is basically just an image control, where different images that correspond to each control state are displayed, is that simple. The hard part is to dinamically create the images used, and do it fast so the user interface reacts promptly. Doing some caching of certain GDI+ objects used, of the png style files in a public property to minimize disk access, I managed to get to about 1.8 seconds for the first run of a form, between form load and form init in a form with 200 controls. Subsequent runs take about 1.5 seconds, so we are saving 300 milliseconds due to caching. Maybe I could get more speed, but in a standard form with 20 of these controls, it takes between 150 and 180 milliseconds to build the 20 controls. Not a bad number. ABOUT GDI TEXT DRAWING At first I used GDI+ to do the text rendering of the caption, but the results where apalling. The size and shape of letters was all wrong compared to native VFP labels or any other standard Windows control font. Some minutes on Google revealed that basically GDI+ sucks for User Interface text, so I decided to switch to classic GDI. This is where the problems started: The bottom line is how the text looked when drawn with GDI using a transparent background. The top line is text drawn using an opaque background, but that is useless because we can have styles with non-uniform color backgrounds. I tried a couple of things, and obtained poor results, and then I got to the point where I had to draw the native radio control, this is what happened: The left one is what I got, the right one is correct. At this point I had no idea what was happening, after all I was using DrawThemeBackground. a Windows API function, to draw the control, so it could not be me doing it wrong. And by the way, the right image is drawn using the same exact API call but to the VFP _screen hwnd. The problem was that I was working with GDI+, and when the time came to use GDI, we have to get a DC from GDI+ to do the classic stuff, using the gdiplus API function GdipGetDC that is supposed to give you a "copy" of the image, where you can draw with GDI, and then you "give it back" to GDI+ with a call to GdipReleaseDC. To make a long story short, the text had a problem with cleartype that involves semitransparent pixels, and the DrawThemeBackground had a problem with semitransparent pixels, so basically it was the same problem in both cases. Now the question was why DrawText and DrawThemeBackground where acting like they where drawing in a black bitmap, instead of using the actual image as background. After a couple of days, I finally found the answer here: http://support.microsoft.com/kb/867631 When the Graphics::GetHDC() method is called, a memory HDC internal method is created, and then a new HBITMAP handle object is created and is put in the memory HDC internal method. This new memory bitmap is not initialized with the original image of the bitmap. This new memory bitmap is initialized with a sentinel pattern that enables GDI+ graphics object to track changes to the new memory bitmap. Any changes that are made to the new memory bitmap by using the GDI code become noticeable in the changes to the sentinel pattern. When the Graphics::ReleaseHDC() method is called, those changes are copied back to the original bitmap. Because the new memory bitmap is not initialized with the image of the original bitmap, anHDC internal method that is obtained in this way is considered "write only."So, it was GDI+ that was cheating and not giving the image as it should in the GdipGetDC. I finally solved this by doing the following: I create a temporary hbitmap from the gpbitmap using GdipCreateHBITMAPFromBitmap, I create a GDI brush with this hbitmap using CreatePatternBrush, I get the DC with GdipGetDC, I draw the original image to this DC using FillRect and the brush, get rid of the hbitmap, and now I have a DC that does have the original image, and then DrawText and DrawThemeBackground work as expected. I am shure there is a performance penalty for all this, but the bitmaps are small, and it works, so thatīs the end of this story. ABOUT ICO FILES Ico files can be used as source for the picture of the control. GDIPLUS can read and parse ICO files, but makes some mistakes when doing it. To understand the problem, we have to understand what ICO files are. An ICO file is just a file that can contain one or more images inside of it. TO DO: finish this. |
This is a mirror of what was originally at www.ctl32.com.ar by CARLOS ALLOATTI, rescued by the webarchive.org - Fantastic VFP Classes, like the CTL32 ActiveX: Scrollable container, BalloonTip, ScrollBars, DatePicker, FormState, Gripper, ProgressBar, StatusBar, TrackBar, Animation, ContextMenu, Month Calendar, Raw Print, Registry, SizeBox, FormState, FTP, LibCurl
Ctl32 TBZ Toolbar buttons for Visual FoxPro
Subscribe to:
Posts (Atom)
No comments:
Post a Comment