So far I haven't found anything in the SDK about assigning attributes [bold, italic, red, font face=Arial, etc.] to single characters or substrings within a string to be drawn by DrawText or another text output function. Something like HTML tags would be OK.
Can anyone suggest a pointer for further research?
You won't find :bg .. The fastest text drawing procedure is ExtTextOut the only possible solution is drawing a range of characters in one pass with appropriate attributes (then do another pass...another..until everything is done ), or simpler one char in one pass (but it isn't very fast)
Quote from: ramguru on April 25, 2007, 09:55:54 AM
You won't find :bg .. The fastest text drawing procedure is ExtTextOut the only possible solution is drawing a range of characters in one pass with appropriate attributes (then do another pass...another..until everything is done ), or simpler one char in one pass (but it isn't very fast)
OK. I was afraid the answer might be something like that [but thanks for the tip about ExtTextOut. I haven't explored ExtTextOut much yet, but I don't want to lose the tab and crlf [0A0Dh] processing that DrawTextEx allows].
If an API function that does what I want doesn't exist, then I'll have to write a procedure that does - something like:
LFtextout proc hdc,....,ADDR string,...
...
invoke ExtTextOut ...,nextsubstring,...
...
invoke ExtTextOut ...,nextsubstring,...
...
invoke ExtTextOut ...,nextsubstring,...
...
LFtextout endp
But this seems like such an obvious and useful routine that someone must already have written something like it, in MASM or C or whatever.
Can you [or anyone] suggest tips that might speed my search for such?
The font face and effects used come from whichever font is currently selected into the device context, so whenever you want to change any of these you'll have to create another font, select that in, and then draw text with it. This doesn't include colour though, which comes from the current text colour attribute (held by the graphics context.)
But you're right, it is something that would be useful, yet I don't know of any available function to do it. Most people simply opt for a RichEdit control (though there is still some setup associated with it.)
I suppose the nicest way of doing it would be to be able to insert 'markers' into the string which indicate a change in face/effect/colour, which is passed to the magic function who handles the necessary font creation, drawing parts, etc; that said, re-creating numerous fonts every refresh isn't going to be too efficient, so some method of caching them would probably be a good idea.
Quote from: raleeper on April 25, 2007, 10:42:33 AM
LFtextout proc hdc,....,ADDR string,...
...
invoke ExtTextOut ...,nextsubstring,...
...
invoke ExtTextOut ...,nextsubstring,...
...
invoke ExtTextOut ...,nextsubstring,...
...
LFtextout endp
ExtTextOut is good not only that it's fast, but one can change background color using it, so THE procedure could look like this:
LFtextout proc hdc,....,ADDR string,...
... parse string looking for markers as Ted said
...
invoke SetBkColor, ps.hdc, color1a
invoke SetTextColor, ps.hdc, color2a
invoke ExtTextOut ...,nextsubstring,...
...
invoke SetBkColor, ps.hdc, color1b
invoke SetTextColor, ps.hdc, color2b
invoke ExtTextOut ...,nextsubstring,...
...
invoke SetBkColor, ps.hdc, color1c
invoke SetTextColor, ps.hdc, color2c
invoke ExtTextOut ...,nextsubstring,...
...
LFtextout endp
Actually it was done many times by many people (mostly for text editors that support syntax highlighting), but no one bothered to write a unique procedure.
Another factor you learn from syntax highliting is if its only display you need, you only need to write to the visible display area. If its document you need, RTF is probably the easiest way to handle te text characteristics and you display it with a rich edit control set to read and write RTF.
Raleeper,
Scintilla is an open source editing component. You can find the source here. (http://scintilla.sourceforge.net/ScintillaDownload.html)
I've never viewed the source but I can imagine it is c++. Should be helpful regardless.
Hope this helps,
Tim
Quote from: hutch-- on April 25, 2007, 11:17:59 AM
Another factor you learn from syntax highliting is if its only display you need, you only need to write to the visible display area. If its document you need, RTF is probably the easiest way to handle te text characteristics and you display it with a rich edit control set to read and write RTF.
"rich edit control"? - [bzzzzz - working]
Thanks.
"rich edit control"? - [bzzzzz - working]
SDK section on Rich Edit Controls almost unintelligible. All that computes is "A rich edit control is a window [for text]".
[bzzzzz - still working].
Thanks.
Quote
The SDK says:
To create a rich edit control, call the CreateWindowEx function, specifying the rich edit window class. If you are using Rich Edit 1.0 (Riched32.dll), specify RichEdit for the window class parameter. If you are using Rich Edit 2.0 or later (Riched20.dll), specify RICHEDIT_CLASS for the window class parameter.
So, instead of Eczelion's
ClassName db "SimpleWinClass",0
for
mov wc.lpszClassName,OFFSET ClassName for
invoke RegisterClassEx, addr wc
and
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ ....
I should use:
ClassName db "RICHEDIT_CLASS"?
And after I've made that simple change, DrawTextEx or ExtextOut will understand and properly handle all the richtext controls??
[bzzzzz - still working - looks like I may need help, but not yet].
...not exactly :bdg
Okay, well it IS a window (that displays text)... just as a 'normal' edit control does. And in the same way that you 'tell' an edit control to display text, so you do with a rich-edit control -- you do this by sending it messages (usually ones that start EM_.... ) which indicate what text you want to insert, and others for the display options, etc..
See the attachment to start you off (removed - see below.)
Quote from: Tedd on April 27, 2007, 09:45:28 AM
...not exactly :bdg
See the attachment to start you off :wink
Thanks Tedd. When I try to open richy.zip I get "The compressed ... folder is invalid or corrupt". Do I need some other zip utility?
Nope, just an ordinary zip file. Maybe the windows unzip dll (or whatever you're using) has some problem with it ::)
I've attached it again just to be sure.
But the code's not that long, so..
.586
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
include gdi32.inc
includelib gdi32.lib
;***************************************************************************************************
WinMain proto
WndProc proto hwnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
RichAppend proto pBuff:DWORD,col:DWORD
;***************************************************************************************************
WIN_WIDTH equ 320
WIN_HEIGHT equ 240
IDRICH1 equ 10001
;***************************************************************************************************
.data
ClassName db "richtest",0
AppName db "Richy",0
RichDLL db "Riched20.dll",0
RichClass db "RichEdit20A",0
;;some test strings
nl db 13,10,0
strS db "Server: ",0
strC db "Client: ",0
msg1 db "Hello",13,10,0
msg2 db "May I help you?",13,10,0
msg3 db "Give me root access",13,10,0
msg4 db "I don't think so",0
msg5 db " -- GO AWAY!!",13,10,0
msg6 db "<Disconnected>",0
.data?
hInstance HINSTANCE ?
hWnd HWND ?
hRichDLL HMODULE ?
hRWnd HWND ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke WinMain
invoke ExitProcess, eax
;***************************************************************************************************
WinMain proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
mov [wc].cbSize,SIZEOF wc
mov [wc].style,CS_HREDRAW or CS_VREDRAW
mov [wc].lpfnWndProc,OFFSET WndProc
mov eax,hInstance
mov [wc].hInstance,eax
invoke LoadIcon, NULL,IDI_APPLICATION
mov [wc].hIcon,eax
invoke LoadCursor, NULL,IDC_ARROW
mov [wc].hCursor,eax
mov [wc].hbrBackground,COLOR_WINDOW+1
mov [wc].lpszClassName,OFFSET ClassName
xor eax,eax
mov [wc].cbClsExtra,eax
mov [wc].cbWndExtra,eax
mov [wc].lpszMenuName,eax
mov [wc].hIconSm,eax
invoke RegisterClassEx, ADDR wc
invoke CreateWindowEx, NULL,ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,WIN_WIDTH,WIN_HEIGHT,NULL,NULL,hInstance,NULL
.IF (eax)
push ebx
mov hWnd,eax
invoke ShowWindow, hWnd,SW_SHOWDEFAULT
invoke UpdateWindow, hWnd
lea ebx,[msg]
assume ebx:ptr MSG
.WHILE TRUE
xor eax,eax
invoke GetMessage, ebx,eax,eax,eax
.BREAK .IF(!eax)
invoke TranslateMessage, ebx
invoke DispatchMessage, ebx
.ENDW
mov eax,[ebx].wParam
assume ebx:nothing
pop ebx
.ENDIF
ret
WinMain endp
WndProc proc hwnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
;-- WM_SIZE -----------------------------------------------------------------------------------------
.IF (eax==WM_SIZE)
mov eax,lParam
mov edx,eax
and eax,0ffffh ;width
shr edx,16 ;height
invoke MoveWindow, hRWnd,0,0,eax,edx,TRUE
;-- WM_CREATE ---------------------------------------------------------------------------------------
.ELSEIF (eax==WM_CREATE)
;need to make sure the dll is loaded - so we can access the richedit control
;(this only needs to be done once)
invoke LoadLibrary, ADDR RichDLL
mov hRichDLL,eax
;** create a richedit window
invoke CreateWindowEx, WS_EX_CLIENTEDGE,ADDR RichClass,NULL,WS_VISIBLE or WS_CHILD or WS_VSCROLL or ES_MULTILINE or ES_READONLY,0,0,0,0,hwnd,IDRICH1,hInstance,NULL
mov hRWnd,eax
;** limit text to 4MB
invoke SendMessage, hRWnd,EM_EXLIMITTEXT,NULL,0400000h
;** set a nicer font
invoke GetStockObject, DEFAULT_GUI_FONT ;could also use: SYSTEM_FIXED_FONT, OEM_FIXED_FONT
invoke SendMessage, hRWnd,WM_SETFONT,eax,TRUE
;** print some stuff
invoke RichAppend, ADDR strC,07f7f7fh ;grey
invoke RichAppend, ADDR msg1,0ff0000h ;blue
invoke RichAppend, ADDR strS,07f7f7fh ;grey
invoke RichAppend, ADDR msg2,07f007fh ;magenta
invoke RichAppend, ADDR strC,07f7f7fh ;grey
invoke RichAppend, ADDR msg3,0ff0000h ;blue
invoke RichAppend, ADDR strS,07f7f7fh ;grey
invoke RichAppend, ADDR msg4,07f007fh ;magenta
invoke RichAppend, ADDR msg5,00000ffh ;bright red
invoke RichAppend, ADDR msg6,0007fffh ;orange
;-- WM_DESTROY -------------------------------------------------------------------------------------
.ELSEIF (eax==WM_DESTROY)
invoke PostQuitMessage, NULL
;-- default ----------------------------------------------------------------------------------------
.ELSE
invoke DefWindowProc, hwnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
RichAppend proc pBuff:DWORD,col:DWORD
LOCAL charrng:CHARRANGE
LOCAL charfmt:CHARFORMAT
mov eax,-1
mov charrng.cpMax,eax
mov charrng.cpMin,eax
mov charfmt.cbSize,SIZEOF CHARFORMAT
mov charfmt.dwMask,CFM_COLOR
mov eax,col
mov charfmt.crTextColor,eax
invoke SendMessage, hRWnd,EM_EXSETSEL,NULL,ADDR charrng
invoke SendMessage, hRWnd,EM_SETCHARFORMAT,SCF_SELECTION,ADDR charfmt
invoke SendMessage, hRWnd,EM_REPLACESEL,FALSE,pBuff
invoke SendMessage, hRWnd,EM_SCROLLCARET,NULL,NULL ;scroll the text into view
ret
RichAppend endp
end start
[attachment deleted by admin]
And once you've got the hang of that..
Here's the proper reference for Rich-Edit Controls :bg
http://msdn2.microsoft.com/en-us/library/ms651298.aspx
Quote from: Tedd on May 03, 2007, 12:11:53 PM
And once you've got the hang of that..
Here's the proper reference for Rich-Edit Controls :bg
http://msdn2.microsoft.com/en-us/library/ms651298.aspx
Thanks Tedd.
I'm working thru richy [actually rich2] now. [I have a day job & can only spend an hour - maybe steal another - on this.
The assembler didn't recognize HMODULE - tho it's in the SDK docs - but hey, handles are just dwords, and the program assembles & works fine w/ that change.
I don't really know enough at this point to have an opinion, but it seems to me that instead of
hRichDLL HMODULE ?
it would be better from several points of view to use:
hRichDLL DD ? ;handle to module - ret'd by !LoadLibrary
And of course, to save a few bytes, your 'save as type: asm' routine (optionally) skips "tab,;" and anything after on/in that (line).
Best Wishes,
RAL
A slave is yet a slave if his master
Allows him to make any decision
About which he, the master,
Is utterly indifferent.
[rel: snowflake..., causation,aggregation,responsibility,...]
Quote from: raleeper on May 04, 2007, 11:04:52 AM
I'm working thru richy [actually rich2] now. [I have a day job & can only spend an hour - maybe steal another - on this.
That's okay, we all do - just work at your own pace, when you have the chance/motivation :wink
Quote
The assembler didn't recognize HMODULE - tho it's in the SDK docs - but hey, handles are just dwords, and the program assembles & works fine w/ that change.
I don't really know enough at this point to have an opinion, but it seems to me that instead of
hRichDLL HMODULE ?
it would be better from several points of view to use:
hRichDLL DD ? ;handle to module - ret'd by !LoadLibrary
True, it is just a dword in reality, but the reason for using 'types' in asm at all is more for self documentation - it can make the code easier to understand. The value returned by LoadLibrary has more meaning than simply being 'just' a dword, it is a handle, so it's good to make note of that. You could equally define it as HINSTANCE - they're really the same (and both are really 'just' dwords) - though the definition for HMODULE should be in windows.inc, along with the one for HINSTANCE. Anyway, like I said, it doesn't make too much difference, it's just for making the code easier to understand.
Quote
And of course, to save a few bytes, your 'save as type: asm' routine (optionally) skips "tab,;" and anything after on/in that (line).
..what routine??
On snowflakes, etc: yep :wink
Quote from: Tedd on May 03, 2007, 12:11:53 PM
And once you've got the hang of that..
Here's the proper reference for Rich-Edit Controls :bg
http://msdn2.microsoft.com/en-us/library/ms651298.aspx
I'm working thru richy again, and I can't seem to find any documentation for RichAppend, even at msdn2.com [or of course, the SDK or Google].
Is there some other source or have I just missed it?
Thanks
RichAppend is my function (found at the end of the code) - it just appends the text you give it, setting the text colour.
..looks a bit like this :lol
RichAppend proc pBuff:DWORD,col:DWORD
LOCAL charrng:CHARRANGE
LOCAL charfmt:CHARFORMAT
mov eax,-1
mov charrng.cpMax,eax
mov charrng.cpMin,eax
mov charfmt.cbSize,SIZEOF CHARFORMAT
mov charfmt.dwMask,CFM_COLOR
mov eax,col
mov charfmt.crTextColor,eax
invoke SendMessage, hRWnd,EM_EXSETSEL,NULL,ADDR charrng
invoke SendMessage, hRWnd,EM_SETCHARFORMAT,SCF_SELECTION,ADDR charfmt
invoke SendMessage, hRWnd,EM_REPLACESEL,FALSE,pBuff
invoke SendMessage, hRWnd,EM_SCROLLCARET,NULL,NULL ;scroll the text into view
ret
RichAppend endp
What you will want to do is look-up what each of the messages sent to the rich-edit control does - at the link provided previously :wink
e.g. RichEdit Controls -> RichEdit Controls Reference -> Messages -> EM_SETCHARFORMAT
Quote from: Tedd on May 31, 2007, 11:30:35 AM
RichAppend is my function (found at the end of the code) - it just appends the text you give it, setting the text colour.
Doh! Right in front of me.
Thanks.