Bcx EDitor (BED)

Started by MrBcx, December 14, 2020, 07:46:53 PM

Previous topic - Next topic

MrBcx

Quote from: morgan on June 10, 2024, 06:31:55 PM
i hope you learned something

I learned a few things. 

I researched and learned when wanting to capture the "/" key,

ASC("/") and VK_OEM_2 might seem to be the same thing but they are not.

VK_OEM_2 = 191

ASC("/")    =  47

I also learned that WM_KEYDOWN and WM_KEYUP receive their messages
before WM_CHAR, so if one is not paying close attention, the state
of TRUE or FALSE may not be what you think it is.

And finally, I learned I should not assume that any code that you post on
this forum has actually been tested in the context being discussed.


morgan

Quote from: Robert on June 10, 2024, 07:12:52 PM
Quote from: morgan on June 10, 2024, 06:31:55 PM
your code is the same as mine
only the key is not the one you were looking for.

my code with wm_char  is very important.
it works with every key you want to use
especially with keys that scintilla use.

for example test mine and yours, with
ctrl+X

EDIT: i didn't even looked at the rest of the code.
i only tried to show you how to do the subclass correct
and catch the keys.
i hope you learned something

Hi morgan:

Thanks for the WM_CHAR tip. You taught me something. I appreciate that help.



GUI "GetKey"

SUB FORMLOAD
  GLOBAL Form1 AS HWND
  Form1 = BCX_FORM("GetKey", 0, 0, 110, 110)
  BCX_SET_FORM_COLOR(Form1,QBCOLOR(31))
  CENTER(Form1)
  SHOW(Form1)
END SUB

BEGIN EVENTS
  SELECT CASE CBMSG
  CASE WM_GETDLGCODE
    FUNCTION=DLGC_WANTALLKEYS
  CASE WM_KEYDOWN
    IF ((wParam BAND VK_CONTROL) AND (WM_CHAR BAND ASC("X")) THEN
      MSGBOX "Beware The X !"
    END IF
    SELECT CASE wParam
    CASE VK_CONTROL
      IF (WM_CHAR BAND ASC("X")) THEN
        MSGBOX "Control The X !"
      END IF
    END SELECT
  END SELECT
END EVENTS

no problem.
but for this to work, the wm_char should has a separate case
like wm_keydown has.

MrBcx

Armando,

Your NewSciProc () is elegant in its simplicity and I think your approach to
incorporating all the parts is completely reasonable.

Scintilla's use of Ctrl+/ and CTRL+\ is sometimes useful, so I'm not keen on
making this subclass a permanent part of BED but with your permission, I'd
like to incorporate your comments toggle into BED's context menu.



Robert

Quote from: morgan on June 10, 2024, 06:31:55 PM
your code is the same as mine
only the key is not the one you were looking for.

my code with wm_char  is very important.
it works with every key you want to use
especially with keys that scintilla use.

for example test mine and yours, with
ctrl+X

EDIT: i didn't even looked at the rest of the code.
i only tried to show you how to do the subclass correct
and catch the keys.
i hope you learned something

Hi morgan:

Thanks for the WM_CHAR tip. You taught me something. I appreciate that help.



GUI "GetKey"

SUB FORMLOAD
  GLOBAL Form1 AS HWND
  Form1 = BCX_FORM("GetKey", 0, 0, 110, 110)
  BCX_SET_FORM_COLOR(Form1,QBCOLOR(31))
  CENTER(Form1)
  SHOW(Form1)
END SUB

BEGIN EVENTS
  SELECT CASE CBMSG
  CASE WM_GETDLGCODE
    FUNCTION=DLGC_WANTALLKEYS
  CASE WM_KEYDOWN
    IF ((wParam BAND VK_CONTROL) AND (WM_CHAR BAND ASC("X")) THEN
      MSGBOX "Beware The X !"
    END IF
    SELECT CASE wParam
    CASE VK_CONTROL
      IF (WM_CHAR BAND ASC("X")) THEN
        MSGBOX "Control The X !"
      END IF
    END SELECT
  END SELECT
END EVENTS

airr

Hi, Morgan.

As long as the _exposed_ API remains the same, it should continue to work going forward.

AIR.

morgan

air is it good for future versions ?
or you need to change the sdk every time you get new one ?

airr

I did this a bit differently.

I added a new file, Sci_Custom_Shortcuts.inc (for future stuff) which contains:


FUNCTION NewSciProc(hwnd as HWND, msg as UINT, wParam as WPARAM, lParam as LPARAM, uIdSubclass as UINT_PTR, dwRefData as DWORD_PTR) as LRESULT STDCALL
    SELECT CASE msg
        CASE WM_KEYDOWN
            IF (GetKeyState(VK_CONTROL) AND &H8000) <> 0 THEN
                IF wParam = VK_OEM_2 THEN
                    ToggleComment()
                    RETURN 0
                END IF
            END IF
    END SELECT
    RETURN DefSubclassProc(hwnd, msg, wParam, lParam)
END FUNCTION


In Sets_Types.inc, I added this to the KeyTable ACCEL:


FCONTROL|FVIRTKEY       , VK_OEM_2, IDM_TOGGLE_COMMENT  ' Toggle Comments CTRL-/


In Sci_Enums.inc, I added the IDM_TOGGLE_COMMENT:


    IDM_COMMENT                       ' Block comment
    IDM_UNCOMMENT                     ' Block uncomment
    IDM_TOGGLE_COMMENT                ' Toggle Block comment




Finally, in Scintilla_Support.inc, between "pSciWinData" and "g_SciLexer" I added:


SetWindowSubclass(ScihWnd, NewSciProc, 0, 0)


And the ToggleComment() function:


SUB ToggleComment()
    DIM RAW i
    DIM RAW curpos
    DIM RAW Line$
    DIM RAW lch
    DIM RAW selStartPos = SCICMD (SCI_GETSELECTIONSTART, 0, 0)
    DIM RAW selEndPos   = SCICMD (SCI_GETSELECTIONEND, 0, 0)-1
    DIM RAW selStartLine = SCICMD (SCI_LINEFROMPOSITION, selStartPos, 0)
    DIM RAW selEndLine   = SCICMD (SCI_LINEFROMPOSITION, selEndPos, 0)
    DIM RAW allCommented = 1
    DIM RAW lineStartPos
    DIM RAW lineLength
    DIM RAW buffer$

    SCICMD (SCI_BEGINUNDOACTION, 0, 0)

    ' Check if all lines are commented
    FOR i = selStartLine TO selEndLine
        CLEAR (Line$)
        SCICMD (SCI_GETLINE, i, Line$)
        lch = *LTRIM$(Line$)
        IF lch THEN
            IF LEFT$(LTRIM$(Line$), 1) <> "'" THEN
                allCommented = 0
                EXIT FOR
            END IF
        END IF
    NEXT i

    ' Toggle comments
    FOR i = selStartLine TO selEndLine
        CLEAR (Line$)
        SCICMD (SCI_GETLINE, i, Line$)
        lch = *LTRIM$(Line$)
        IF lch THEN
            curpos = SCICMD (SCI_POSITIONFROMLINE, i, 0)
            IF allCommented THEN
                ' Uncomment the line
                IF LEFT$(LTRIM$(Line$), 1) = "'" THEN
                    lineStartPos = SCICMD (SCI_POSITIONFROMLINE, i, 0)
                    buffer$ = LTRIM$(Line$)
                    lineLength = LEN(buffer$)
                    buffer$ = MID$(buffer$, 2, lineLength - 1)
                    SCICMD (SCI_SETTARGETSTART, lineStartPos + (INSTR(Line$, "'") - 1), 0)
                    SCICMD (SCI_SETTARGETEND, lineStartPos + INSTR(Line$, "'"), 0)
                    SCICMD (SCI_REPLACETARGET, -1, "")
                END IF
            ELSE
                ' Comment the line
                SCICMD (SCI_INSERTTEXT, curpos, "'")
            END IF
        END IF
    NEXT i

    SCICMD (SCI_ENDUNDOACTION, 0, 0)
END SUB



Different way, same result?

AIR.

morgan

#67
 your code is the same as mine
only the key is not the one you were looking for.

my code with wm_char  is very important.
it works with every key you want to use
especially with keys that scintilla use.

for example test mine and yours, with
ctrl+X

EDIT: i didn't even looked at the rest of the code.
i only tried to show you how to do the subclass correct
and catch the keys.
i hope you learned something

Robert


GUI "GetKey"

SUB FORMLOAD
  GLOBAL Form1 AS HWND
  Form1 = BCX_FORM("GetKey", 0, 0, 110, 110)
  BCX_SET_FORM_COLOR(Form1,QBCOLOR(31))
  CENTER(Form1)
  SHOW(Form1)
END SUB

BEGIN EVENTS
  SELECT CASE CBMSG
  CASE WM_GETDLGCODE
    FUNCTION=DLGC_WANTALLKEYS
  CASE WM_KEYDOWN
    IF ((wParam BAND VK_CONTROL) AND (wParam BAND 0xBF)) THEN
      MSGBOX "Beware The Slash !"
    END IF
    SELECT CASE wParam
    CASE VK_CONTROL
      IF (wParam BAND 0xBF) THEN
        MSGBOX "Control The Slash !"
      END IF
    END SELECT
  END SELECT
END EVENTS


MrBcx

Quote from: morgan on June 10, 2024, 05:52:52 PM

i didn't ofcurse checked the key
i just built it upon your code.
so my code is actually works very well
only the key wasn't the right one.


I tested your code with VK_OEM_2.  It did not work.  Also, as I showed in
my final code, it is not necessary to handle the WM_CHAR message.

That said, thank you for participating in the discussion.  We arrived at a solution
and that's the most thing here.

morgan

#64

i didn't ofcurse checked the key
i just built it upon your code.
so my code is actually works very well
only the key wasn't the right one.

MrBcx

#63
Armando, et al

This subclass proc is working now and should give you the springboard you were looking for.

My original code has been update:  https://bcxbasiccoders.com/smf/index.php?topic=420.msg5601#msg5601


CALLBACK FUNCTION NewSciProc
    SELECT CASE CBMSG

    CASE WM_KEYDOWN
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = TRUE
        END IF
        IF ctrlPressed AND CBWPARAM = VK_OEM_2  THEN    ' VK_OEM_2 is the / key
            toggleState = NOT toggleState
            ToggleAction(CBHWND)
            FUNCTION = 0
        END IF

    CASE WM_KEYUP
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = FALSE
        END IF
        IF ctrlPressed AND CBWPARAM = VK_OEM_2 THEN     ' VK_OEM_2 is the / key
            toggleState = NOT toggleState
            ToggleAction(CBHWND)
            FUNCTION = 0
        END IF

    END SELECT

    FUNCTION = CallWindowProc(oldSciProc, CBHWND, CBMSG, CBWPARAM, CBLPARAM)
END FUNCTION



It will popup the MSGBOX's but you need to click back into the editor window to
give the window focus after you close the MSGBOX.  Of course when you implement
your comments on/off toggle, focus should not change.




MrBcx

#62
Quote from: morgan on June 10, 2024, 04:57:45 PM

' New Scintilla subclass procedure  <<<<< --  FOR AIR
' Declare a few new global variables

GLOBAL toggleState AS LONG
GLOBAL oldSciProc AS LONG_PTR
GLOBAL ctrlPressed AS LONG

CALLBACK FUNCTION NewSciProc
    SELECT CASE CBMSG
    CASE WM_KEYDOWN
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = TRUE
        END IF
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN FUNCTION = 0     
    CASE WM_KEYUP
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN FUNCTION = 0
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = FALSE
        END IF
    CASE WM_CHAR
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN
            toggleState = NOT toggleState
            ToggleAction(CBHWND)
            FUNCTION = 0
            EXIT FUNCTION
        END IF
    END SELECT
    FUNCTION = CallWindowProc(oldSciProc, CBHWND, CBMSG, CBWPARAM, CBLPARAM)
END FUNCTION


SUB ToggleAction(hWnd AS HWND)    ' Eventually replace with your comment toggle code
    IF toggleState THEN
        MessageBox(hWnd, "Toggle ON", "Info", MB_OK)
    ELSE
        MessageBox(hWnd, "Toggle OFF", "Info", MB_OK)
    END IF
END SUB



Morgan,

That does not work. 
I'll post my new code in a moment.

morgan


' New Scintilla subclass procedure  <<<<< --  FOR AIR
' Declare a few new global variables

GLOBAL toggleState AS LONG
GLOBAL oldSciProc AS LONG_PTR
GLOBAL ctrlPressed AS LONG

CALLBACK FUNCTION NewSciProc
    SELECT CASE CBMSG
    CASE WM_KEYDOWN
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = TRUE
        END IF
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN FUNCTION = 0     
    CASE WM_KEYUP
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN FUNCTION = 0
        IF CBWPARAM = VK_CONTROL THEN
            ctrlPressed = FALSE
        END IF
    CASE WM_CHAR
        IF ctrlPressed AND CBWPARAM = ASC("/") THEN
            toggleState = NOT toggleState
            ToggleAction(CBHWND)
            FUNCTION = 0
            EXIT FUNCTION
        END IF
    END SELECT
    FUNCTION = CallWindowProc(oldSciProc, CBHWND, CBMSG, CBWPARAM, CBLPARAM)
END FUNCTION


SUB ToggleAction(hWnd AS HWND)    ' Eventually replace with your comment toggle code
    IF toggleState THEN
        MessageBox(hWnd, "Toggle ON", "Info", MB_OK)
    ELSE
        MessageBox(hWnd, "Toggle OFF", "Info", MB_OK)
    END IF
END SUB


morgan

#60
not now
check wparam for '/'
in wm_keydown/up
(of curse in case of ctrl)
and
return 0
instead of callwindowproc