|
Post by neuropsychddx on Sept 10, 2021 12:29:40 GMT -5
I am new to LB, but have learnt it quite well in a couple of days. To test my skills I have developed a Notepad clone in Liberty BASIC. I does not have the word wrap function. Apart from that the statusbar can update if CAPS, INS or NUM are on. Not able to figure out how to get the Line and Column position of the cursor in the edit box. Please guide. Attachments:notepad1.bas (8.27 KB)
|
|
|
Post by Walt Decker on Sept 10, 2021 16:40:21 GMT -5
First, I think you are using the wrong widget. Check Custom Edit Ctrl in the Liberty BASIC code thread. Second, you are using the getcaretpos() function correctly but you need more data. You have to combine the x, y parameters into one variable and then use the em.charfrompos message to get the position of the character and the line. Check out NUMBERS in the API and DLL code thread to combine the x, y values.
PS: You might also check out "Things You Don't Want to Know. . ." in the "General Discussion" thread.
|
|
|
Post by Walt Decker on Sept 11, 2021 18:32:19 GMT -5
I have modified the code so the status bar works correctly. To run the code the below dll is included:
' 'Form created with the help of Freeform 3 v07-31-2015 'Generated on Sep 05, 2021 at 17:22:20
[setup.main.Window]
'-----Begin code for #main
nomainwin '<-------------- MODIFIED CODE ------------------> ES.MULTILINE = HEXDEC("&H0004") ES.AUTOVSCROLL = HEXDEC("&H0040") ES.AUTOHSCROLL = HEXDEC("&H0080") ES.NOHIDESEL = HEXDEC("&H0100") ES.WANTRETURN = HEXDEC("&H1000")
WS.VSCROLL = HEXDEC("&H00200000")
EM.CHARFROMPOS = HEXDEC("&H00D7") OPEN "NUMBERMANDLL1.DLL" FOR DLL AS #NUM OPEN "User32.dll" FOR DLL AS #USER
WindowWidth = 550 WindowHeight = 440 UpperLeftX=int((DisplayWidth-WindowWidth)/2) UpperLeftY=int((DisplayHeight-WindowHeight)/2)
'-----Begin GUI objects code global fileName$ global filestatus global fileN$
EdtHndl = 0
fileN$ = "Untitled"
TexteditorColor$ = "white" '<---------------- MODIFIED CODE -----------------------> ' texteditor #main.textedit3, 5, 22, 525, 330 STYLEBITS #main.textedit3, ES.MULTILINE OR ES.AUTOVSCROLL OR ES.WANTRETURN OR _ EX.NOHIDESEL OR WS.VSCROLL, ES.AUTOHSCROLL, 0, 0 TEXTBOX #main.textedit3, 5, 22, 525, 330 groupbox #main.groupbox1, fileN$, 0, 2, 535, 355 'statictext #main.statictext4, "Line 1 Col 1 CAPS INS NUM", 2, 362, 535, 20
'-----End GUI objects code
'-----Begin menu code
menu #main, "File",_ "New" , [filenew],_ "Open" , [fileopen],_ "Save" , filesave,_ "Save as", filesaveas,|,_ "Print" , [fileprint],|,_ "Quit" , [quit.main]
menu #main, "Edit" ' <-- Texteditor menu.
menu #main, "Font",_ "Change font", [fontchange]
menu #main, "Help",_ "About", [aboutapp]
'-----End menu code
open "Liberty Notepad v0.1" for window as #main print #main, "font segoe_ui 9" print #main, "trapclose [quit.main]" print #main.textedit3, "!font courier_new 10"
'----Begin code for statusbar
h=hwnd(#main) EdtHndl = HWND(#main.textedit3) '<--- MODIFIED CODE 'print #main.textedit3, "!origin? columnVar rowVar " ; value$ = "Line "; rowVar; " Col "; columnVar styleValue = _WS_VISIBLE or _WS_CHILD hStatusBar=initalizeStatusBar(h,value$) print #main, "resizehandler [resizeStatusbar]" timer 500, [updatestats]
'----End code for statusbar
struct caretpos, _ xpos as long, _ ypos as long
struct tagsize, _ cx as long, _ cy as long
[main.inputLoop] 'wait here for input event wait
[updatestats] CallDLL #user32, "GetKeyState", _VK_CAPITAL as Long, result as Long If result <> 0 Then capsres$ = " CAPS " Else capsres$ = " " End If CallDLL #user32, "GetKeyState", _VK_INSERT as Long, result as Long If result <> 0 Then insres$ = " INS " Else insres$ = " " End If CallDLL #user32, "GetKeyState", _VK_NUMLOCK as Long, result as Long If result <> 0 Then numres$ = " NUM " Else numres$ = " " End If CallDLL #user32, "GetCaretPos", caretpos as struct, result as Long If result <> 0 Then '<------------- MODIFIED CODE ------------------------> wParam = caretpos.xpos.struct lParam = caretpos.ypos.struct CALLDLL #NUM, "FN_SetLong", wParam AS SHORT, lParam AS SHORT, lParam AS LONG CALLDLL #USER, "SendMessageA", EdtHndl AS ULONG, EM.CHARFROMPOS AS ULONG, _ 0 AS LONG, lParam AS LONG, wParam AS LONG CALLDLL #NUM, "FN_GetLowWord", wParam AS LONG, columnVar AS SHORT CALLDLL #NUM, "FN_GetHiWord", wParam AS LONG, rowVar AS SHORT
'hndl = hwnd(#main.textedit3) 'lpstring$ = "A" 'lpstringlen = len(lpstring$) 'CallDLL #gdi32, "GetTextExtentPoint32A", hndl as ulong, lpstring$ as ptr, lpstringlen as long, tagsize as struct, result as long 'print #main.textedit3, result 'If result <> 0 Then 'rowVar = caretpos.ypos.struct / tagsize.cy.struct 'columnVar = caretpos.xpos.struct / tagsize.cx.struct 'End if 'rowVar = caretpos.ypos.struct 'columnVar = caretpos.xpos.struct Else rowVar = -1 columnVar = -1 End If value$ = "Line "; rowVar; " Col "; columnVar; capsres$; insres$; numres$ a = SendMessagePtr(hStatusBar,_WM_SETTEXT,0, value$) goto [main.inputLoop]
[filenew] 'Perform action for menu File, item New 'Insert your own code here filestatus = CheckFileModified() if filestatus = 1 then confirm "File has changed, do you want to save changes?"; answer$ if answer$ = "yes" then 'write file save routine here if fileN$ = "Untitled" then call filesaveas else call filesave end if end if fileN$ = "Untitled" print #main.groupbox1, fileN$; print #main.textedit3, "!cls"; wait
[fileopen] 'Perform action for menu File, item Open filestatus = CheckFileModified() if filestatus = 1 then confirm "Do you want to save first?"; answer$ if answer$ = "yes" then 'write file save routine here if fileN$ = "Untitled" then call filesaveas else call filesave end if end if 'Insert your own code here filedialog "Open text file", "*.txt", fileName$ if fileName$ <> "" then print #main.groupbox1, fileName$; open fileName$ for input as #1 print #main.textedit3, "!contents #1"; 'print #main.textedit3, "!origin 1 1"; close #1 fileN$ = fileName$ end if wait
SUB filesave 'Perform action for menu File, item Save if fileN$ = "Untitled" then call filesaveas exit sub else print #main.textedit3, "!contents? edited$" open fileName$ for output as #1 print #1, edited$ close #1 end if END SUB
SUB filesaveas 'Perform action for menu File, item Save as filedialog "Save file", "*.txt", fileNewName$ if fileNewName$ <> "" then print #main.textedit3, "!contents? edited$" open fileNewName$ for output as #1 print #1, edited$ close #1 fileName$ = fileNewName$ fileN$ = fileNewName$ print #main.groupbox1, fileN$; end if END SUB
[fileprint] 'Perform action for menu File, item Print
'Insert your own code here 'print #main.textedit3, "!origin?"; 'input #main.textedit3, rowVar,columnVar 'print #main.textedit3, "!contents?"; 'input #main.textedit3, saveit$ 'lprint saveit$ 'dump 'print #main.textedit3, "!origin ";rowVar;" ";columnVar;""; wait
[fontchange] 'Perform action for menu Font, item Change font
'Insert your own code here fontdialog "arial 10 italic", chosenFont$ if chosenFont$ <> "" then print #main.textedit3, "!font "; chosenFont$ wait end if wait
[changeMessageBar] '----This changes the text in the statusbar '----Change the text in value$ then gosub this routine a = SendMessagePtr(hStatusBar,_WM_SETTEXT,0, value$) wait
[resizeStatusbar] '----This makes the statusbar fit when window is resized wWid = WindowWidth wHig = WindowHeight print #main.groupbox1, "!locate 0 2 "; wWid; " "; wHig-20; print #main.textedit3, "!locate 5 22 "; wWid-10; " "; wHig-47; a= SendMessageLong(hStatusBar,_WM_SIZE,0,WindowWidth) print #main, "refresh" wait
'----End of statusbar resizer code
[aboutapp] 'Perform action for menu Help, item About
'Insert your own code here Notice "Liberty Notepad ver 0.1 programmed in Liberty BASIC ver 4.5.1 by JagSOFT 2021." wait
[quit.main] 'End the program filestatus = CheckFileModified() if filestatus = 1 then confirm "File has been changed, do you want to save changes? Press no if already saved."; answer$ if answer$ = "yes" then if fileN$ = "Untitled" then call filesaveas else call filesave end if end if end if '<------------------- MODIFIED CODE ---------------------> CLOSE #USER CLOSE #NUM close #main end
'------------------------------------------------------ '----------------- Subs and Functions ----------------- '------------------------------------------------------
FUNCTION initalizeStatusBar(h, value$)
calldll #comctl32,"InitCommonControls",_ result as long
styleValue = _WS_VISIBLE or _WS_CHILD calldll #comctl32,"CreateStatusWindow",_ styleValue as long,_ value$ as ptr,_ h as long,_ 22 as long,_ r as long initalizeStatusBar=r END FUNCTION
FUNCTION SendMessagePtr(hWnd,msg,w,p$) CallDLL #user32, "SendMessageA",_ hWnd As long, _ msg As long,_ w As long,_ p$ As ptr,_ SendMessagePtr As long END FUNCTION
FUNCTION SendMessageLong(hStatusBar,msg,w,p) CallDLL #user32, "SendMessageA",_ hStatusBar As long, _ msg As long,_ w As long,_ p As long,_ SendMessagePtr As long END FUNCTION
FUNCTION CheckFileModified() print #main.textedit3, "!modified? textmodified$" ; retval=0 if textmodified$ = "true" then retval=1 CheckFileModified=retval END FUNCTION
'------------------------------------------------------ '--------------- End Subs and Functions --------------- '------------------------------------------------------ '
|
|
|
Post by neuropsychddx on Sept 12, 2021 11:08:27 GMT -5
Dear Walt,
Thanks for the detailed response.
I ran the code along with the DLL and it worked fine. However, I noticed that you have shifted from using a texteditor to a textbox. The textbox does not work as intended. It does not go to the nextline on pressing enter. Also, I cant use "!modified?" to check whether the text has changed and does the user needs to be prompted to save the file.
Thanks.
|
|
|
Post by Walt Decker on Sept 12, 2021 12:14:42 GMT -5
That is correct. The reason for the shift is "texteditor" is a proprietary control. It does not respond to EM... messages sent to it so you can never find the correct row and column. To place a crlf in the editbox control you use CTRL + ENTER or trap VK_RETURN and insert crlf at the position intended. To determine if the edit control is modified use the EM.GETMODIFY message (&H00B8) You were trying to calculate the character position. You can not do that for either the textedit or the textbox until you create a corresponding font for use with gettextextentex32. If you try it without creating the font you will get the size of the system font. LB uses its own handles, not windoz handls, for the font. Even then you can not properly calculate the position in LB if the font is not a fixed font. The reason is you have to use font functions that are not usable in LB. I have made some additional modifications to your code: ' EM.LINELENGTH = HEXDEC("&H00C1") EM.LINEINDEX = HEXDEC("&H00BB")
'<------------- MODIFIED CODE ------------------------> ChrIdx = -1
wParam = caretpos.xpos.struct lParam = caretpos.ypos.struct CALLDLL #NUM, "FN_SetLong", wParam AS SHORT, lParam AS SHORT, lParam AS LONG CALLDLL #USER, "SendMessageA", EdtHndl AS ULONG, EM.CHARFROMPOS AS ULONG, _ 0 AS LONG, lParam AS LONG, wParam AS LONG CALLDLL #NUM, "FN_GetLowWord", wParam AS LONG, columnVar AS SHORT CALLDLL #NUM, "FN_GetHiWord", wParam AS LONG, rowVar AS SHORT
CALLDLL #USER, "SendMessageA", EdtHndl AS ULONG, EM.LINEINDEX AS ULONG, _ rowVar AS LONG, 0 AS LONG, ChrIdx AS LONG columnVar = columnVar - ChrIdx + 1 '
This now gives the correct line and column within the line. If you intend the following to indicate that text can be over-written or is inserted at the character position, it needs more work: ' CallDLL #user32, "GetKeyState", _VK_INSERT as Long, result as Long If result <> 0 Then insres$ = " INS " Else insres$ = " " End If '
You will have to determine if VK_SHIFT or VK_CONTROL is pressed while VK_INSERT is pressed. I assume you know how to do that, if not let me know in this thread.
PS: In Addendum V, "MONITOR THE KEYBOARD" of "Things You Do Not Want to Know..." there is an outline for what you are attempting.
PPS: You will find that your edit menu item does not work so you will have to float your own.
gettextextent32() requires a device context, not a handle to the control. Get the handle to the control then use getdc() to obtain a device context.
|
|
|
Post by Walt Decker on Sept 15, 2021 17:05:21 GMT -5
Hmm. I guess the OP decided creating a notepad style edit control is not worth the effort. Too bad. He had something rather interesting started.
|
|