- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am attempting to read the text of a button in order to transfer it to another. The text of the first, IDCANCEL, is set in the resource file as Cancel without the inverted commas. When I use the command to read the text into the character*20 ButtonStr:
lBtnStr = GetWindowText(hButton, ButtonStr, 20) ! Get Button text.
The return value of lBtnStr is 19, rather than the expected 6.
The 7th to 20th characters of ButtonStr are not uniform blanks, do not contain any nulls = char(0) but do contain the occasional alphanumeric character.
When subsequently written into another button, it is treated as being of length 19, not 6, which ruins the centering.
Other WinAPIs are no better or worse, with GetWindowTextLength returning 280 and GetDlgItemText 19.
Any ideas please?
Llynisa
Link Copied
- « Previous
-
- 1
- 2
- Next »
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks - alot to digest there. I will produce a stripped-down version of my program and post it here, also try some of the diagnostics you suggest.
Unfortunately I am just about to have my pacemaker changed at short notice (one of the delights of geriatricity), so there may be a delay. At least the new pacemaker will be internet-compatible.
Llynisa
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
On BS_OWNERDRAW style and XFLogm, the best answer that I can suggest is to look at Yugoslavs info at:http://www.xeffort.com/fortran/xflogm/xflogm.htm
I attach the files necessary to build a simple version of my program whilst I look into debugging it.
Create an empty Fortran Windows Application project and add the files BtnClrA.f90, XFLogm.f90, BtnClrA.rc, BtnClrA.h & BtnClrA.fd. If you are using CVF, they should build an .exe without trouble, but for IVF, make changes appropriately. The .exe that I have built is attached as BtnClrA.exe and its displayed dialogue box is as in BtnClrA.jpg.
The method of drawing and colouring the button is simple, with the edges of the button being uncoloured. Also the coloured centre does not move one pixel sideways and down when clicked upon. If anyone can advise me how to incorporate these refinements, it would be greatly appreciated.
Llynisa
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
At the instant of dialog creation the control is created with the "right" text, but during WM_INITDLG processing by XFLOGM the control's text is explicitly changed to include the trailing blanks. You can see that in the following message trace:
![](/skins/images/8492E06DAD1A420837AF16E991F628F9/2021_redesign/images/image_not_found.png)
The offending call is on line 1848 of the XFLOGM.f90 that you attached. The text of the control has been parsed out of the resource template by previous parts of the library into a fixed length character variable (the only sort available prior to F2003 - now that would probably be better off being an deferred length allocatable component, i.e. CHARACTER(:), ALLOCATABLE :: xxx, alternatively the trailing null sentinel could have been left in the component's value or the signficant length tracked separately). You could also just TRIM the text argument of the WM_SETTEXT message, or just TRIM the results of your GetWindowText call in your code - it is probably fair enough to assume that trailing blanks will never be significant in a window's caption.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The present code fails in that case by assuming that the second part of the test
i .le. len(str0.and. str(i:i) .ne. char(0)
will not be executed if i exceeds len(str), which it will do because of the i=i+1.
(This has been discussed in a recent thread). The attached code is better as it exits the WHILE loop as soon as i exceeds len(str) and prevents the code trying to access str(i:i) when i exceeds the strings length.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! PadStrFor
!!
!! Pads out a null terminated string (C string to F90 string)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
recursive subroutine PadStrFor( str )
character*(*), intent(inout) :: str
integer i, lstr
! scan up to the terminating null
i = 1
lstr=len(str)
do while( i .le. lstr.and. str(i:i) .ne. char(0) )
i = i + 1
if(i.gt.lstr) exit
end do
! pad the rest with blanks
do while( i .le. lstr )
str(i:i) = ' '
i = i + 1
end do
end subroutine PadStrFor
P.S.
GetWindowText help says "If the function succeeds, the return value is the length, in characters, of the copied string, not including the terminating null character." (my emphasis). So any terminating null character is ignored by this function during the copy to the user-supplied buffer. Clearly, if there is no terminating null character, the function may copy some rubbish to the user-supplied buffer, up to the end of the buffer holding the window's text.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I might not have correctly followed what you are saying here, but while the returned length doesn't include the terminating null, the api (or the target window proc handling the WM_GETTEXT message) will always append a terminating null (unless the target window proc is doing something daft, or the programmer has passed in a zero length buffer). Otherwise you'd have C programs exploding all over the shop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks to all of you for getting me started - I dug back to where the text was read and set. It appears to me that the offendingplacein XFlogm is line 5267:
ctrlHeader%textName(iSt:iSt)=" "
iSt =7, so it sets not a terminating null but a space.
changing the line to:
ctrlHeader%textName(iSt:iSt)=char(0) !" " BearofLittleBrain amendment.
solves the problem and gives thecorrect text display in the button.
I've only tested it in the one example program that I posted, but it feels as if it is the correct fix.
BearofLittleBrain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I substituted a routine called DrawButton for your button-colouring routine to draw the correct frame using the DrawEdge function and to draw the button text using function DrawText. This is done in response to a WM_DRAWITEM message sent by both owner-draw style buttons, Apply and Exit.
If you use DrawFrameControl, it always draws a frame with the default background, it appears, so I had to drop using that.
The colouring of the button backgrounds is done by first intercepting the WM_CTLCOLORBTN mesage for the Apply and Exit buttons and returning a handle to the required background brush in each case.
I think the only fortran file I have not modified is CVFCOLOURS. Button colour choices are made in the BackColorSub callback routine on initialisation of the dialog, and colours and control window handles etc are saved in the BackColorGlobals module for use wherever they are required.
I have added code to add a terminating char(0) to each text string before drawing it on a button.
I include screen dumps of the dialog with and without a clicked Apply button. A message box is put up when the Apply button is clicked.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Congratulations - that looks just the ticket! A minor query - should the button centre not move 1 pixel right & down rather than left & up when pushed?
Yes, I recognised thatDrawFrameControlblocked out the centre, so yours is a better approach. I will take a longer look at it later and see what set of mods to XFLOGM are needed following yourlast proposal on double-clicking, your previous one on PadStrFor and mine on adding a terminal null.
Llynisa
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can play with the edge style used in the DrawEdge function to suit using the one or more of the various options, of which BF_RECT is just one. You can draw a black frame Rectangle around it to show it has focus too.
e.g.
if(BtnState.and.ODS_SELECTED) then
iret=DrawEdge(hdccontrol,RC,EDGE_SUNKEN,BF_TOPRIGHT)
!Draw frame rectangle if button selected
iret=FrameRect(hdccontrol, RC, GetStockObject(BLACK_BRUSH))
or
IF(GetFocus().eq.hbutton) iret=FrameRect(hdccontrol, RC, GetStockObject(BLACK_BRUSH))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ctrlHeader%textName(iSt:iSt)=" "
should be changed to:
ctrlHeader%textName(iSt:iSt)=char(0) !" " AJC modification.
Similarly
ctrlHeader%className(iSt:iSt)=" "
should be changed to
ctrlHeader%className(iSt:iSt)=char(0) !" " AJC modification.
Then one can get rid of LenTrimAll, which is only used in desperation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
![](/skins/images/98E68944C1FF703B8AC50091329B92AF/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- « Previous
-
- 1
- 2
- Next »