|
Post by turtleman on Jul 1, 2024 10:37:53 GMT -5
Once upon a time, probably over 4 years ago, I asked if there was a way of changing the background color of one of several textboxes selected by a mouse click. I'd like the normally white textbox background to change to blue (or any other color) when selected, and revert to white upon after changing the contents and hitting Enter.
I'm pretty sure someone posted a working solution, but it seems to have disappeared. (Actually, I can no longer find many of my old posts and replies.) Next time I'll be sure to save the solutions elsewhere. Thanks in advance!
|
|
|
Post by Chris Iverson on Jul 1, 2024 19:19:05 GMT -5
|
|
|
Post by turtleman on Jul 2, 2024 8:43:39 GMT -5
Thanks Chris, but I can't seem to get the examples to work in my application. I can click any of several textboxes and enter new numbers just fine. What I want, however, is to indicate the textbox has been selected by changing its normally white background to a colored background. Once new data has been entered, the background should go back to white. It's only a cosmetic function, but it would be nice to have the color change to indicate that the textbox has been selected. I hope that makes sense. Thanks!
|
|
|
Post by Walt Decker on Jul 2, 2024 11:57:03 GMT -5
Since you do not have access to the program callback function, changing the background color of an edit control on the fly requires use of API. Knowing your aversion for using DLL/API, I doubt that you will be able to accomplish the task.
1 - you need to determine which edit control currently has the focus. Requires API function GetFocus()
2 - you need to use API functions to change the background color via CTL_COLOREDIT handler. This entails the use of the LB callback function.
3 - when finished entering data you need a way to indicate that the operation is complete, probably a button.
4 - you need a way to change back to the original color.
Is it really worth the effort?
|
|
|
Post by Walt Decker on Jul 2, 2024 12:52:42 GMT -5
You could substitute a graphic for the edit control. This would require a string variable for each graphic, a method to determine which graphic is selected (API again), and a method to monitor key strokes and concatenate each keystroke to the appropriate string. When data is complete you would have to clear the graphic, restore the white background and print the text to the graphic.
With this method additional problems arise that may be difficult to surmount.
|
|
|
Post by turtleman on Jul 3, 2024 10:32:40 GMT -5
Thanks for your comments – much appreciated. I'm still thinking there must be a way of indicating when a textbox has been selected, or perhaps a listbox or other input/display might be better suited. Unfortunately, as is often the case, other issues take precedence, so I may not be able to get back to this until sometime next week.
|
|
|
Post by Walt Decker on Jul 4, 2024 11:40:42 GMT -5
You could create two edit controls (text boxes) with different background colors at the same location and hide the first one. When the control has the focus, display the hidden one, get the text from the currently displayed control and copy the text to the other then re-hide the first one. This method still requires a method to determine when the control is selected and when data entry is completed; it requires a method to monitor control focus via a call to winapi user32.dll function GetFocus().
Pseudo-code:
OPEN USER32.DLL FOR DLL AS #USER
txbforegroundcolor txbbackgroundcolor TEXTBOX T.TXB1
txbforegroundcolor txbbackgroundcolor TEXTBOX T.TXB2
BUTTON #T.TXBDONE [TXB.DONE] WINDOW #T
TxbHndl1 = HWNDL(#T.TXB1)
[BEGIN.TIMER] TIMER 120 [MONITOR.TXTBX]
WAIT
[MONITOR.TXTBX] TIMER 0 CALLDLL #USER, GetFocus, TxbHndl
IF TxbHndl = TxbHndl1 THEN T.TxbHndl2 "show!" END IF GOTO BEGIN.TIMER END.MONITOR.TXTBX]
[TXB.DONE] #T.TXB1 "contents!", Cont$ #T.TXB2 Cont$ #T.TXB1 "Hide!" GOTO BEGIN.TIMER [END.TXB.DONE]
|
|
|
Post by turtleman on Jul 5, 2024 4:51:37 GMT -5
Walt: Actually, I'm already doing exactly what you suggested by duplicating a dozen textboxes and hiding and showing to display two different colors. That works great, but is not controlled by a mouse click.
As you said, what I need is "a method to monitor control focus" so a textbox color can changed with a mouse click on the selected textbox. I just haven't been able to figure out how to detect when a textbox has been selected with the mouse! If a status flag is set when a textbox is selected, I haven't yet found it.
Your mention of "a call to winapi user32.dll function GetFocus()", is perhaps the hint I need and I'm researching how to incorporate that function. A simple (?) example of changing textbox color with a left click would probably be all I need. What little I've learned comes mostly from code examples. Thanks again for all your help!
|
|
|
Post by Rod on Jul 5, 2024 5:21:23 GMT -5
I hope Walt has a solution but getfocus() will tell you what control has focus but it will not help with knowing that the focus has changed. No event is passed in Liberty.
Solutions in the past have involved a timed checking loop and noting and managing focus change. Messy.
|
|
|
Post by turtleman on Jul 5, 2024 6:39:36 GMT -5
I don't totally understand, but a "timed checking loop" is probably what I was referring to in my original post that someone was kind enough to share. It's fuzzy now, but I almost got it to do what I wanted and thought I'd tackle it again. I just wish I had saved the code, as most ancient history no longer appears on the site.
Not being able to change color when a textbox is selected isn't a deal breaker, but rather more like an obsession – LOL!
|
|
|
Post by Walt Decker on Jul 5, 2024 12:53:31 GMT -5
After thinking a bit there is another way to hilite the selected edit control; however this requires two API calls using user32.dll functions GetClientRect(hwnd, structPtr) and InvertRect(hwnd, structPtr). This changes the white background to black and the black text to white. If the colors are other than white, black the InvertRect function uses the boolean AND operator to invert the colors.
As far as determining which of multiple edit controls is selected the easiest solution is to add a button that indicates when entry is completed. This requires an action flag containing the control handle and an array containing the handles of each control pair plus the LB control tag e. g. #dmo.btn1. With this you would simply parse through the array looking for the element that matches the action flag. The button handler would look something like this:
[BUTTON.DONE]
I = 0 FOR I = 0 TO NumEdit IF EditFlag = VAL(EditAry(I, 0)) THEN EdtTag$ = EditAry$(I, 2) #EdtTag$, "!Contents"; Txt$ #EdtTag$, "!Hide" EdtTag$ = EditAry$(I, 1) #EdtTag$, Txt$ #EdtTag$, "!Show" END IF NEXT I EditFlag = 0 WAIT [END.BUTTON.DONE]
If you do not want to use a button API function GetFocus() is still usable. The code might look something like this:
PSEUDO-CODE - 2 EDIT CONTROLS
DIM EditAry$(1, 2)
GLOBAL EditFlag GLOBAL LastEdit
TextboxBkgColor = "blue" TextBoxTxtColor = "White" TEXTBOX #DMO.TXT1 '<-- hidden control
TextboxBkgColor = "White" TextBoxTxtColor = "Black" TEXTBOX #DMO.TXT2
TextboxBkgColor = "blue" TextBoxTxtColor = "White" TEXTBOX #DMO.TXT3 '<--- hidden control
TextboxBkgColor = "White" TextBoxTxtColor = "Black" TEXTBOX #DMO.TXT4
WINDOW #DMO
#DMO.TXB1, "!HIDE" #DMO.TXB3, "!HIDE"
EditAry$(0, 0) - STR$(HWND(#DMO.TXB2)) EditAry$(0, 1) = "#DMO.TXB1 EditAry$(0, 2) = "#DMO.TXB2"
EditAry$(1, 0) - STR$(HWND(#DMO.TXB4)) EditAry$(1, 1) = "#DMO.TXB3" EditAry$(1, 2) = "#DMO.TXB4"
[BEGIN.TIMER] TIMER 150, [CHECK.FOCUS] WAIT
'----------------------- '-----------------------
[CHECK.FOCUS]
TIMER 0
EditTag.1$ = "" EditTag.2$ = "" EditHndl = 0 I = 0
CALLDLL #user32, GetFocus, EditHndl
FOR I = 0 TO 1 IF EditHndl = VAL(EditAry$(I, 0)) THEN IF EditFlag = 0 THEN EditFlag = EditHndl LastEdit = I EditTag.1$ = EditAry$(I, 1) #EditTag.1$, "!Hide" #EditTag.2$ = EditAry$(I, 2) #EditTag.2$, "!Show" #EditTag2$, "!SetFocus" GOTO BEGIN.TIMER END IF EditTag.1$ = EditAry$(LastEdit, 2) #EditTag.1$, "!Contents"; Txt$ #EditTag.1$, "!Hide" #EditTag.2$ = EditAry$(LastEdit, 1) #EditTag.2$, Txt$ #EditTag.2$, "!Show"
EditFlag = EditHndl LastEdit = I
EditTag.1$ = EditAry$(I, 1) #EditTag.1$, "!Hide" #EditTag.2$ = EditAry$(I, 2) #EditTag.2$, "!Show" #EditTag.2$, "!SetFocus" GOTO BEGIN.TIMER END IF NEXT I [END.CHECK.FOCUS]
One may also use user32.dll function GetActiveWindow() retrieve the handle of the control; however, I see no advantage in doing so.
|
|
|
Post by Rod on Jul 5, 2024 14:42:28 GMT -5
I have not had time to code but I think the issue is that we have no way of knowing that a text box has received focus either by mouse or tab. A button has too many bypasses , tab , mouse , to be useful.
Only way I have seen is if a timer is running and checks for focus but this can easily destroy program flow.
A graphicbox can know and I have posted graphic box solutions before but it’s a big step change in programming style.
|
|
|
Post by Rod on Jul 5, 2024 14:55:25 GMT -5
As Walt has said, it’s all an awful lot of work to color a textbox that the user has eyes on anyway, has clicked or tabbed to and is intent on completing. Perhaps if the input sequence of text boxes are “themed” ie all colored the same it might be easier to code and guide the user.
|
|
|
Post by Walt Decker on Jul 5, 2024 15:49:52 GMT -5
Another thought to use only a single control for changing color: use the CTL_COLOR.DLL found at Enhance you conrols. READ THE DOCUMENTATION and peruse the example.
|
|
|
Post by Chris Iverson on Jul 5, 2024 18:29:06 GMT -5
Here's an alternate version of my color change test. Unfortunately, this requires the use of TWO extra DLLs(one to handle colors, one to handle window notifications), but the good news is, it has exactly the behavior you're looking for. Focus on a textbox, and that textbox's background color changes. Change to a different one, it goes back to normal. Also, the color is fully customizable. Use any RGB values you want in the global variable at the beginning of the program. Please note that, because this uses a DLL called WMLiberty, this code CANNOT use a WAIT statement. Instead, it uses a SCAN/sleep loop. Attachments:color-change-test.zip (22.52 KB)
|
|