flat assembler
Message board for the users of flat assembler.
Index
> Windows > Writing to an Edit Control Goto page 1, 2, 3, 4 Next |
Author |
|
revolution 28 Jul 2024, 00:06
You can use EM_SETCARETINDEX to change the position of the cursor.
|
|||
28 Jul 2024, 00:06 |
|
Walter 28 Jul 2024, 00:39
You might also consider letting the control figure out where to place the cursor for you:
Code: invoke SendMessage,[edithwnd],EM_SETSEL,0,-1 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 invoke SetFocus,[edithwnd] |
|||
28 Jul 2024, 00:39 |
|
Stancliff 29 Jul 2024, 00:04
sounds like a plan, will try.
I was trying GetCursorPos and SetCursorPos but didn't define the structure for the cursor right. They say it is LPPOINT for GetCursorPos but SetCursorPos didn't recognize it or I referenced it wrong. Walter, I added those lines and got it to compile but it immediately dies when I try to run, nothing at all shows it started. The child didn't even open. |
|||
29 Jul 2024, 00:04 |
|
Stancliff 29 Jul 2024, 00:21
A careless mistake caused an infinite loop, but I am rather certain the text didn't print in my Edit Control, I need more changes to be sure. Will be back tomorrow.
|
|||
29 Jul 2024, 00:21 |
|
revolution 29 Jul 2024, 00:22
In MS-speak the "cursor" is the mouse pointer. The "caret" is the position of the vertical flashing bar in the edit window.
Do you want to move the cursor or the caret? |
|||
29 Jul 2024, 00:22 |
|
Stancliff 29 Jul 2024, 00:58
revolution wrote: In MS-speak the "cursor" is the mouse pointer. The "caret" is the position of the vertical flashing bar in the edit window. Is the caret where the system and user will type text? That would be what I need to move. I am trying to make system messages print on sequential lines, but the printing start point isn't moving when the messages print. I am fairly certain the second message is overwriting the first. Separate question... I want the msg_loop to be a separate thread so it handles messages independently. CreateThread wants a parameter pointing to an LPSECURITY_ATTRIBUTES structure and FASM isn't recognizing the name. There is still too much I don't know... especially when the examples are in C and I am in FASM. |
|||
29 Jul 2024, 00:58 |
|
Hrstka 29 Jul 2024, 10:49
In most cases you can pass 0 to LPSECURITY_ATTRIBUTES. This is equivalent to NULL.
|
|||
29 Jul 2024, 10:49 |
|
Walter 29 Jul 2024, 14:09
An example to demonstrate:
Quote: I need a way to force the cursor Code: ; Simple example program format PE GUI 4.0 entry start include 'win32a.inc' IDR_MENU = 100 IDM_M1 = 101 IDM_M2 = 102 IDM_M3 = 103 IDM_EXIT = 104 section '.text' code readable executable start: invoke GetModuleHandle,0 mov [wc.hInstance],eax invoke LoadIcon,eax,IDI_APPLICATION mov [wc.hIcon],eax invoke LoadCursor,0,IDC_ARROW mov [wc.hCursor],eax invoke RegisterClass,wc test eax,eax jz error invoke LoadMenu,[wc.hInstance],IDR_MENU invoke CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_OVERLAPPEDWINDOW,144,128,256,256,NULL,eax,[wc.hInstance],NULL test eax,eax jz error msg_loop: invoke GetMessage,msg,NULL,0,0 cmp eax,1 jb end_loop jne msg_loop invoke TranslateMessage,msg invoke DispatchMessage,msg jmp msg_loop error: invoke MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK end_loop: invoke ExitProcess,[msg.wParam] proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi mov eax,[wmsg] cmp eax,WM_CREATE je .wmcreate cmp eax,WM_SIZE je .wmsize cmp eax,WM_SETFOCUS je .wmsetfocus cmp eax,WM_COMMAND je .wmcommand cmp eax,WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmcreate: invoke GetClientRect,[hwnd],client invoke CreateWindowEx,WS_EX_CLIENTEDGE,_edit,0,WS_VISIBLE+WS_CHILD+WS_HSCROLL+WS_VSCROLL+ES_AUTOHSCROLL+ES_AUTOVSCROLL+ES_MULTILINE,[client.left],[client.top],[client.right],[client.bottom],[hwnd],0,[wc.hInstance],NULL or eax,eax jz .failed mov [edithwnd],eax invoke CreateFont,16,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH+FF_DONTCARE,NULL or eax,eax jz .failed mov [editfont],eax invoke SendMessage,[edithwnd],WM_SETFONT,eax,FALSE xor eax,eax jmp .finish .failed: or eax,-1 jmp .finish .wmsize: invoke GetClientRect,[hwnd],client invoke MoveWindow,[edithwnd],[client.left],[client.top],[client.right],[client.bottom],TRUE xor eax,eax jmp .finish .wmsetfocus: invoke SetFocus,[edithwnd] xor eax,eax jmp .finish .wmcommand: mov eax,[wparam] and eax,0FFFFh cmp eax,IDM_M1 je .m1 cmp eax,IDM_M2 je .m2 cmp eax,IDM_EXIT je .wmdestroy jmp .defwndproc .m1: invoke SendMessage,[edithwnd],WM_SETTEXT,0,strMsg1 invoke SendMessage,[edithwnd],EM_SETSEL,0,-1 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 jmp .finish .m2: invoke SendMessage,[edithwnd],WM_SETTEXT,0,strMsg2 invoke SendMessage,[edithwnd],EM_SETSEL,0,-1 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 jmp .finish .wmdestroy: invoke DeleteObject,[editfont] invoke PostQuitMessage,0 xor eax,eax .finish: pop edi esi ebx ret endp section '.data' data readable writeable strMsg1 db 'Message #1',0 strMsg2 db 'Message #2: Line #1',13,10,'Line #2.',0 _title TCHAR 'MiniPad',0 _error TCHAR 'Startup failed.',0 _class TCHAR 'MINIPAD32',0 _edit TCHAR 'EDIT',0 wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class edithwnd dd ? editfont dd ? msg MSG client RECT section '.idata' import data readable writeable library kernel,'KERNEL32.DLL',\ user,'USER32.DLL',\ gdi,'GDI32.DLL' import kernel,\ GetModuleHandle,'GetModuleHandleA',\ ExitProcess,'ExitProcess' import user,\ RegisterClass,'RegisterClassA',\ CreateWindowEx,'CreateWindowExA',\ DefWindowProc,'DefWindowProcA',\ SetWindowLong,'SetWindowLongA',\ RedrawWindow,'RedrawWindow',\ GetMessage,'GetMessageA',\ TranslateMessage,'TranslateMessage',\ DispatchMessage,'DispatchMessageA',\ SendMessage,'SendMessageA',\ LoadCursor,'LoadCursorA',\ LoadIcon,'LoadIconA',\ LoadMenu,'LoadMenuA',\ GetClientRect,'GetClientRect',\ MoveWindow,'MoveWindow',\ SetFocus,'SetFocus',\ MessageBox,'MessageBoxA',\ PostQuitMessage,'PostQuitMessage' import gdi,\ CreateFont,'CreateFontA',\ DeleteObject,'DeleteObject' section '.rsrc' resource data readable directory RT_MENU,menus resource menus,\ IDR_MENU,LANG_ENGLISH+SUBLANG_DEFAULT,main_menu menu main_menu menuitem '&Message',0,MFR_POPUP + MFR_END menuitem '&Message 1',IDM_M1 menuitem '&Message 2',IDM_M2 menuseparator menuitem 'E&xit',IDM_EXIT,MFR_END |
|||
29 Jul 2024, 14:09 |
|
Stancliff 29 Jul 2024, 17:42
Hrstka wrote: In most cases you can pass 0 to LPSECURITY_ATTRIBUTES. This is equivalent to NULL. OK, I will give it a try. Walter - thank you for the example, I appreciate it and have made a copy to study and reread. Walter - I read the program and recognized minipad, I have studied that one a lot recently. I added CR and LF to both messages and the caret is moving to the next line for new input just as I need. On the other hand, the system messages are always starting at (1, 1) in the top left corner and not printing at the caret position, therefore they overwrite each other... is there a way to change this? I am thinking of asking for the line count and trying to write at the next line, but right now I am not certain that will change what this program is doing. |
|||
29 Jul 2024, 17:42 |
|
AsmGuru62 31 Jul 2024, 02:34
The message to use here is EM_REPLACESEL.
|
|||
31 Jul 2024, 02:34 |
|
Stancliff 31 Jul 2024, 22:52
Hi AsmGuru, I had to look at the description of that message about four times before the implication sunk in. I appreciate that it looks like a very good choice.
My current problem is that when I went back this morning to make the changes, my program no longer compiles... all day spent looking for small editing errors I can't find. This is happening a lot to me. I have to go back to minipad and add changes gradually while I test each one. I am finding this whole process to be very fragile or I am just a klutz. The issue might somehow be related to making the msg_loop a separate thread, but that is not where the error is showing and right now I am getting compile errors from the invoke macro when I process a MessageBox function which is basically identical to the ones that work. |
|||
31 Jul 2024, 22:52 |
|
revolution 01 Aug 2024, 01:23
Show the failing code, and the error message you get.
|
|||
01 Aug 2024, 01:23 |
|
AsmGuru62 01 Aug 2024, 15:57
Indeed, the full code post would be great.
I can try and compile it here --- on my version of FASM. I am not sure if you need threads. Also, I want to point out that in a very rare case the code you added somewhere else can affect the compilation of code which had no issues before the change. I had that case once and I write a lot of code in FASM. Also #2: your 1st post says: "I am trying to use the MiniPad example as a simple text screen my app can read lines or write messages to." Ok, can you provide more details? So, you have the MiniPad EXE which just runs. And then you have a 2nd EXE --- "my app" as you say. And you want to manipulate the MiniPad from your app? If I am correct --- this may be not easy, since Windows makes it hard. This would involve the inter-process communication. |
|||
01 Aug 2024, 15:57 |
|
Stancliff 01 Aug 2024, 18:09
I fixed the compile issue, the main problem is that the child window will not 'Create' ever since I tried to make msg_loop a separate thread. Create Window is just before Create Thread so I expected the child to Create even if the new thread crashes the program. The WindowProc isn't running the Create step at all. I have been bringing my app into a copy of the MiniPad file so it is currently too large to just paste here, it will need a lot of trimming... maybe a day or two.
Regarding threads, my app (about 12kb currently) has a process loop to get a command from the keyboard, run it, and display results, then repeat. If this isn't separate from the screen functions, messages are likely to stop being processed while text is waited for. Having the window and msg_loop in a separate thread by themselves would allow them to be independent and not conflict. Avoiding the thread separation would probably require moving my entire app into the WindowProc (in the commands section maybe). I am having trouble seeing how that would be accomplished. The only hint I have to do this is Walter's MiniPad mod above. Since the second thread would run in my app's process space I had hoped inter-process communication would be simplified (the main issue here would seem to be using parent and child handles correctly when passing messages). I will need time to consider this as even a possible option. |
|||
01 Aug 2024, 18:09 |
|
AsmGuru62 01 Aug 2024, 18:26
I see. A nice explanation of what is going on.
There is a special message to use when you communicate with another process: WM_COPYDATA. Just using SendMessage to command the EDIT control (EM_SETSEL, EM_xxx) may not work. It worked in Windows XP, but not today, I think, Windows is much more strict since the days of XP. When you say "while text is waited for" --- I am curious as how do you do that? Are you using CONSOLE application as your app? If you are using WINDOWS application as your app --- then I think there is no waiting there. You just process the WM_CHAR messages and when <ENTER> key is pressed -- then you communicate this fact to the MiniPad. I am just curious, not judging or anything. Usually, threads are used when you "really" need to run two streams of code in "parallel". |
|||
01 Aug 2024, 18:26 |
|
Stancliff 01 Aug 2024, 19:33
My app has never run. I wrote it part-time early this year over about four months, then spent two or three more fixing errors from ignorance of assembly coding and redesigns prompted by an increased understanding of my project.
It has a function that was going to use bios calls to make strings from keystrokes for processing, and output was intended to go straight to the graphics card. Of course this is based on methods from the 70's when my reference books were written. As I was getting the core to compile it was clear the 'old ways' are over 30 years outdated and I needed a better interface, thus windows is the only feasible choice due to availability and market share. That accounts for most of the last month studying windows programming. My initial intent is to use GETLINECOUNT and GETLINE with the app waiting for windows to process the input for me (which assumes the msg_loop is still running). Then I hope to be able to use SETSEL and REPLACESEL to write responses below the line the command was entered on and everything scrolls up. Getting individual keystrokes is certainly an option since I have the frame for it mostly written. The message passing to a child thread is a worry I expect to be able to solve when I get to it, but not if I can't get the child thread to run! The concept of integrating my app into the interface code so there is only one process is comparable to reversing all the letters of each word you want to say and then trying to speak them (all done in your head)... it's just alien. Having my app tell the interface to get a line of text or to print a line of text is straightforward within the limits of what windows will allow. I am still learning those limits at the moment. Needless to say, the documentation I have found so far is confusing and verbose on a good day. I actually start to understand how FASM works now with functionality integrated into a form of the MiniPad editor and processes triggered by the menu choices. The code for that has to be HUGE compared to my program! Late afternoon already, still more to do... |
|||
01 Aug 2024, 19:33 |
|
Stancliff 01 Aug 2024, 22:16
I went back to Walter's code and inserted some of my changes including the CreateThread and it worked. I tried to add a test of the return value and now I get 'Write failed' errors. That was about line 40. Jumping back up to repeat the text posts proves the second thread was running to do messages! End task to break out.
Code: ; Simple example program format PE GUI 4.0 entry start include 'win32a.inc' IDR_MENU = 100 IDM_M1 = 101 IDM_M2 = 102 IDM_M3 = 103 IDM_EXIT = 104 section '.code' code readable executable start: invoke GetModuleHandle,0 mov [wc.hInstance],eax invoke LoadIcon,eax,IDI_APPLICATION mov [wc.hIcon],eax invoke LoadCursor,0,IDC_ARROW mov [wc.hCursor],eax invoke RegisterClass,wc test eax,eax jz error invoke LoadMenu,[wc.hInstance],IDR_MENU invoke CreateWindowEx,0,_class,_title,WS_TILEDWINDOW+WS_VISIBLE,\ 200,100,900,600,NULL,eax,[wc.hInstance],NULL test eax,eax jz error invoke CreateThread,SecAttr,2048,msg_loop,NULL,0,NULL mov [threadhwnd],eax ; need a waiting loop in the absence of my app code posting: invoke SendMessage,[edithwnd],EM_REPLACESEL,0,strMsg1 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 invoke SendMessage,[edithwnd],EM_REPLACESEL,0,strMsg2 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 invoke MessageBox,NULL,Question,NULL,MB_YESNO cmp eax,IDYES je posting jmp end_loop Question: db "Do you want to loop back?",13,10,0 ; A LOT of my code should go here msg_loop: invoke GetMessage,msg,NULL,0,0 cmp eax,1 jb end_loop jne msg_loop invoke TranslateMessage,msg invoke DispatchMessage,msg jmp msg_loop error: invoke MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK end_loop: invoke ExitProcess,[msg.wParam] proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi mov eax,[wmsg] cmp eax,WM_CREATE je .wmcreate cmp eax,WM_SIZE je .wmsize cmp eax,WM_SETFOCUS je .wmsetfocus cmp eax,WM_COMMAND je .wmcommand cmp eax,WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmcreate: invoke GetClientRect,[hwnd],client invoke CreateWindowEx,WS_EX_ACCEPTFILES,_edit,0,ES_AUTOHSCROLL+\ ES_AUTOVSCROLL+ES_MULTILINE+ES_WANTRETURN+WS_CHILD+\ WS_VISIBLE+WS_HSCROLL+WS_VSCROLL,[client.left],\ [client.top],[client.right],[client.bottom],[hwnd],\ 0,[wc.hInstance],NULL or eax,eax jz .failed mov [edithwnd],eax invoke CreateFont,16,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,\ OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ FIXED_PITCH+FF_DONTCARE,NULL or eax,eax jz .failed mov [editfont],eax invoke SendMessage,[edithwnd],WM_SETFONT,eax,FALSE xor eax,eax jmp .finish .failed: or eax,-1 jmp .finish .wmsize: invoke GetClientRect,[hwnd],client invoke MoveWindow,[edithwnd],[client.left],[client.top],\ [client.right],[client.bottom],TRUE xor eax,eax jmp .finish .wmsetfocus: invoke SetFocus,[edithwnd] xor eax,eax jmp .finish .wmcommand: mov eax,[wparam] and eax,0FFFFh cmp eax,IDM_M1 je .m1 cmp eax,IDM_M2 je .m2 cmp eax,IDM_EXIT je .wmdestroy jmp .defwndproc .m1: invoke SendMessage,[edithwnd],EM_REPLACESEL,0,strMsg1 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 jmp .finish .m2: invoke SendMessage,[edithwnd],EM_REPLACESEL,0,strMsg2 invoke SendMessage,[edithwnd],EM_SETSEL,-1,-1 jmp .finish .wmdestroy: invoke DeleteObject,[editfont] invoke PostQuitMessage,0 xor eax,eax .finish: pop edi esi ebx ret endp section '.data' data readable writeable strMsg1 db 'Message #1',13,10,0 strMsg2 db 'Message #2: Line #1',13,10,'Line #2.',13,10,0 _title TCHAR 'MiniPad',0 _error TCHAR 'Startup failed.',0 _class TCHAR 'MINIPAD32',0 _edit TCHAR 'EDIT',0 wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class edithwnd dd ? editfont dd ? threadhwnd dd ? ClassAtom dd ? msg MSG client RECT caret POINT ; caret position struct SEC_ATTR nLength dd ? lpSecurityDescriptor dd ? bInheritHandle db ? ends SecAttr SEC_ATTR section '.idata' import data readable writeable library advapi32, 'ADVAPI32.DLL',\ comctl32, 'CONCTL32.DLL',\ comdlg32, 'COMDLG32.DLL',\ gdi32, 'GDI32.DLL',\ kernel32, 'KERNEL32.DLL',\ shell32, 'SHELL32.DLL',\ user32, 'USER32.DLL',\ wsock32, 'WSOCK32.DLL' include 'api\advapi32.inc' include 'api\comctl32.inc' include 'api\comdlg32.inc' include 'api\gdi32.inc' include 'api\kernel32.inc' include 'api\shell32.inc' include 'api\user32.inc' include 'api\wsock32.inc' section '.rsrc' resource data readable directory RT_MENU,menus resource menus,\ IDR_MENU,LANG_ENGLISH+SUBLANG_DEFAULT,main_menu menu main_menu menuitem '&Message',0,MFR_POPUP + MFR_END menuitem '&Message 1',IDM_M1 menuitem '&Message 2',IDM_M2 menuseparator menuitem 'E&xit',IDM_EXIT,MFR_END Last edited by Stancliff on 02 Aug 2024, 15:44; edited 1 time in total |
|||
01 Aug 2024, 22:16 |
|
revolution 01 Aug 2024, 23:01
Please use code tags. Thanks.
Code: This is in a code tag |
|||
01 Aug 2024, 23:01 |
|
AsmGuru62 02 Aug 2024, 00:19
Why the thread?
The Windows App goes like that: 1. Register Window Class (Fill up WNDCLASS and call RegisterClass API) 2. Call CreateWindowEx API 3. Run message loop: Code: proc Application_Run ; --------------------------------------------------------------------------- local wc:WNDCLASS local message:MSG local xwnd:DWORD local ywnd:DWORD local cxwnd:DWORD local cywnd:DWORD lea edi, [wc] xor ebx, ebx ; ; fill WNDCLASS object ; mov [edi + WNDCLASS.lpszMenuName], ebx mov [edi + WNDCLASS.cbClsExtra], ebx mov [edi + WNDCLASS.cbWndExtra], ebx invoke CreateSolidBrush, 0xFAE6E6 mov [edi + WNDCLASS.hbrBackground], eax invoke LoadCursorW, ebx, IDC_ARROW mov [edi + WNDCLASS.hCursor], eax invoke LoadIconW, ebx, IDI_APPLICATION mov [edi + WNDCLASS.hIcon], eax invoke GetModuleHandleW, ebx mov [edi + WNDCLASS.hInstance], eax mov [edi + WNDCLASS.lpfnWndProc], Application_EventHandler mov [edi + WNDCLASS.lpszClassName], wstr_WndClass or ebx, CS_HREDRAW or CS_VREDRAW mov [edi + WNDCLASS.style], ebx ; ; ask Windows to register it ; invoke RegisterClassW, edi ; ; center main window with some margins ; invoke GetSystemMetrics, SM_CXSCREEN mov edx, eax shr edx, 3 ; 1/8th for width mov [xwnd], edx sub eax, edx sub eax, edx mov [cxwnd], eax invoke GetSystemMetrics, SM_CYSCREEN mov edx, eax shr edx, 4 ; 1/16th for height mov [ywnd], edx sub eax, edx sub eax, edx mov [cywnd], eax ; ; create and show main window ; invoke CreateWindowExW, WS_EX_APPWINDOW, [edi + WNDCLASS.lpszClassName], wstr_WndTitle, \ WS_OVERLAPPEDWINDOW, [xwnd], [ywnd], [cxwnd], [cywnd], 0, 0, [edi + WNDCLASS.hInstance], 0 mov esi, eax invoke ShowWindow, esi, SW_SHOWDEFAULT invoke UpdateWindow, esi ; ; message loop ; lea esi, [message] xor ebx, ebx .while esi invoke GetMessageW, esi, ebx, ebx, ebx .if eax invoke TranslateMessage, esi invoke DispatchMessageW, esi .else xor esi, esi ; stop 'while' loop .endif .endw ret endp |
|||
02 Aug 2024, 00:19 |
|
Goto page 1, 2, 3, 4 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.