News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Editbox Refresh

Started by RedXVII, March 09, 2006, 10:46:05 PM

Previous topic - Next topic

RedXVII

Im getting this color scheme working by the method below but;

When i type text in the edit box and then delete it, the edit box does not refresh. leaving the old text symbols behind, even though its no longer in the edit box buffer. Then, when i add more text, the gdi overwrites over the old symbols making a big mess, you cant see what youre typing.

I am subclssing the editbox so i presume this isprobably causing the problem somewhere. The main wndproc loop is where i have the WM_CTLCOLOREDIT which sets the correct color of the editbox. when i remove this section (comment it out) and recompile, the code works fine again. I dont want to paste the whole thing, cause its pretty big and stuff. So, Here are some of the relevent bits.

...  ;WndProc
.elseif eax==WM_CTLCOLOREDIT
mov eax, lParam
.if eax==hEditID1||hEditID2
invoke SetBkMode, wParam, hdcBackround
invoke SetTextColor, wParam, hdcText
mov eax, hdcBackround
ret
.else
xor eax, eax
ret
.endif

...  ;EditID1proc
.if eax==WM_KEYDOWN
mov eax, wParam
.if eax==VK_RETURN
invoke GetWindowText, hWnd, OFFSET buffer, 128

;Basically, if string is "Setcolor xxxxxx", do this;     :)
invoke CreateSolidBrush, RGBtext
mov hdcText, eax
invoke CreateSolidBrush, RGBbackround
mov hdcBackround, eax
invoke InvalidateRect, hEditID1, NULL, TRUE
invoke InvalidateRect, hEditID2, NULL, TRUE

ret

...



Anyhelp with this would be great.
Thanks for your help and patience
Red  :U

Tedd

You need to cause the editbox to redraw every time its contents change - which means whenever a character is inserted and whenever one is deleted.
This could be done with InvalidateRect each time you receive EN_CHANGE (which comes after the modification has taken place) but since you're subclassing, I suppose you could do it on every keydown? Though that might be a little excessive since not every keydown will cause a modification.
No snowflake in an avalanche feels responsible.

RedXVII

Is that what normally happens when windows refreshs an editbox?

Errr.. how exactly, does adding the WM_CTLCOLOREDIT message to my main wndproc effect the refreshing of the editbox? They seem to me to be quite unrelated, its giving me a headache trying to understand how windows works  :'(

Ill give your suggestion a shot though

Tedd

No, it's because you're subclassing :P
Although, simply subclassing shouldn't produce that effect. So it's something you're doing (or not doing) in response to one of the message.
In any case, the problem comes from the contents not being redrawn :wink


Okay, I've just looked at your code properely ::) - I see what you're doing.
Unfortunately it is still a bit off :P

So you want to modify the colours based on what the user types in? eg "setcolor ff0000" turns it blue, or however you want to specify the colours..
So, once you've got your input string, you'll need to convert it into a binary value for the colour (let's assume you've done that.)
Then you're creating brushes for the fore and background in order to be use for painting - nice idea, but slightly wrong :bdg
Well, you can keep the background brush - that's okay. Just save the handle and keep track of it.
But not so for the text colour. For the ctlcoloredit message, you want to set the attributes for the dc (as given by wparam) and then return the background brush to be used (the one you made earlier).
Sooo... when you're getting the colour values from the user, create your background brush (cus you need that one) but also save the value for the text colour.
[meanwhile, back in ctlcoloredit..] you set the text colour to this value (no brushes involved!)
Meaning..


.if (eax==hEditID1) || (eax==hEditID2)      ; <-- note the difference!!! (two tests, but that's what you really mean)
    invoke SetBkMode, wParam, OPAQUE        ;this probably isn't really necessary, it's usually set by default
    invoke SetTextColor, wParam, rgbtext    ;where 'rgbtext' is the colour value for the text colour (ie. a binary value)
    mov eax, hdcBackround                   ;and return the required background brush
    ret
.else
    xor eax, eax
    ret
.endif


Okay, that should fix it up a bit :green2

(..the InvalidateRect calls upon vk_return are because you're clearing the editbox contents?)
No snowflake in an avalanche feels responsible.

RedXVII

i put in the InvalidateRect after WM_KEYDOWN in my subclass. Works ok now, though i like efficent and very fast programs (one of the reasons i chose assembly). Would i be fair to say this is an inefficient and slackers way of solving this? Having to call it every time a key is pressed; isnt that a complete waste of processing power?

Maybe if i add en extra line,

.if eax==VK_BACKSPACE  ;backspace or delete key
invoke Invalidaterect...

that woud make it better :bg

Tedd

I've just realised that most of the problem comes from your small mistake within the "if"
It means that you always return 0 for the background brush - which is a NULL brush and draws nothing :red


..and yes, repeatedly clearing is an inefficient slackers way of doing it :bdg -- scrap that suggestion and fix as above and see what you get :wink
No snowflake in an avalanche feels responsible.

RedXVII

woops, looks like i posted my last post about 30 seconds after yours and missed the one before  :bg

Youre abasolutely right, my .if statement was all wrong. Its working ok now. I also found out the reason the editbox wasnt refreshing was because i set the editbox to transparent  :red which i thaught meant something else (i thaught that it would set the edit box backround and the text backround colors the same, basically). So, i got rid of SetBkMode and replaced it with SetBkColor to the RGB of the backround color. Works a treat now.

Now, the last problem is getting the ES_READONLY editbox to change color. ES_READONLY locks the edit box to backround grey and text color black. I presume it also doesnt send WM_CTLCOLOREDIT messages aswell. Know a way to change the color of a ES_READONLY edit box?

Im thinking, if all else fails, ill subclass it, that will work  :bg

Anyway Tedd, thanks for your help, youve been really helpful
Cheers  :U

;working code

.elseif eax==WM_CTLCOLOREDIT
mov eax, lParam
.if eax==hEditID1 || eax==hEditID2
invoke SetBkColor, wParam, BackroundRGBColor
invoke SetTextColor, wParam, TextRGBColor
mov eax, hdcBackround
ret
.else
xor eax, eax
ret
.endif

RedXVII

You wouldnt also happen to know how to disable the Paste menu option when you right click on an edit box?

Synfire

I don't know if an edit control set to readonly can have the color changed. Generally when I need such a feature I just subclass, change the color, and add watch for WM_KEYUP and WM_KEYDOWN, and have them return 0 (rather than passing them off to the default window procedure). Returning 0 from these two messages tells the system that you have processed them yourself and the system don't need to deal with them. Another possible choice would be to use a static control rather than an edit control, then just use WM_CTLCOLORSTATIC to change it's color to whatever you want.

Regards,
Bryant Keller

RedXVII

^^ i already subclassed it to just ret nothing when WM_CHAR, WM_KEYDOWN, WM_KEYUP. Trouble is, if you highlight the text and right click you can;

Cut        <-- I want this faded (unselectable)
Copy      <-- I want this
Paste      <-- I want this faded (unselectable)
Delete    <-- I want this faded (unselectable)
Select All <-- I want this

Naturally, being my output text box, this means the user can really screw things up  :'(

Solution?

Tedd

Well I'm not sure exactly what happens when you set the edit box to read-only, but I presume ctlcoloredit will still work. Anyway, the simple way to find out would be to try it :P

And as for mouseclicks, if you're already subclassing, then you can just eat WM_LBUTTON.., WM_RBUTTON.., WM_MBUTTON... messages :toothy
(..and provide your own copy + select all menu?)

Of course, if it's read-only then this is done for you - so try setting it to readonly and see whether it works okay :wink
No snowflake in an avalanche feels responsible.

RedXVII

Errr.... tedd. Thats kinda the whole point. Above i said that if you make it READONLY you cant change the colors, at all it seems; which i want to do, hence, i cant use it.  :'(

Arent there any function to disable certain system menu items for certain handles. Surely there must be a way..... how does windows do it?...

Synfire

#12
Quote from: SynfireAnother possible choice would be to use a static control rather than an edit control, then just use WM_CTLCOLORSTATIC to change it's color to whatever you want.

Tedd

Yeah you're right, sorry - didn't read it properely (again ::))
So I've just had a play with an edit box and I don't see any way to override the readonly stuff apart from doing it all yourself. Answering to CTLCOLOREDIT only works because the edit box asks your opinion, but not when it's set for readonly. So modfying it would require changing its internal behaviour.

To change the contents of a menu is quite straight-forward: the ModifyMenu function will work fine.... but for the small problem of getting the edit-box's menu right-click handle ::)

Anyway, stuff this :bdg

If you change to using a rich-edit box, then you can set the whole text to non-modifiable without any side-effects. Plus, the option to set text colours (yes, multiple) and background colour are all supported options, so there's no need for messing around once you've set it up.



synfire: using a static control works okay, but doesn't provide any text selection/copying - which I think is wanted.
No snowflake in an avalanche feels responsible.

RedXVII

^^ thats some serious richedit advertising  :bg

Sounds good, i havent done the rich text tutorials on iczelions yet. Ill check it out; Cheers

Synfire: Yeah, i need text highlighting like tedd said, so that i can copy output text.  :(

Thanks alot  :U