Win32 GUI version of moving cursor in text?

Using the left and right arrow keys on the keyboard:

C++11
Windows 32 GUI



I have the following code. I have been trying to move the cursor that is in the text via the left and right keys on the keyboard.

I found getch(); and gotoxy(10, 2);, and gotoxy, etc. but I also found multiple places that said similar to: "Note: Do not use this function in Win32 GUI applications."

I looked for a Win32 GUI application version of how to do this but I did not get it.

My question is how to move the mouse cursor from where it is (when I click on the text in the subclassed edit box) to the next text character. I want that to be either the next character or letter on one line if there is one or go to the next line.

Help. Please.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#define _UNICODE
#define UNICODE

#include <windows.h>
#include <iostream>


using namespace std;

wchar_t g_szClassName[] = L"TestOfSubclassing";

LONG g_iResult;

static HWND hSUBCLASSED;
const int IDB_SUBCLASSED_TEXT  = 1000;

static HWND hNORMAL_TEXT1;
const int IDB_NORMAL_TEXT  = 2000;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubclassedEditBoxProceedure(HWND, UINT, WPARAM, LPARAM);



LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
     switch(msg)
     {

        case WM_CREATE:
        {

        // A subclassed edit box.
        hSUBCLASSED = CreateWindowExW(
            WS_EX_CLIENTEDGE,
            L"EDIT",
            L"EDIT BOX\r\nSUBCLASSED\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30",
            WS_CHILD | ES_MULTILINE | WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL,
            10,10,
            300,400,
            hwnd,
            (HMENU) IDB_SUBCLASSED_TEXT,
            GetModuleHandle( nullptr ),
            nullptr
            );

        // Subclassing the edit box "IDB_SUBCLASSED_TEXT".
        g_iResult = (LONG)(LONG_PTR)SetWindowLong(GetDlgItem(hwnd, IDB_SUBCLASSED_TEXT), GWL_WNDPROC,  (LONG)(LONG_PTR)SubclassedEditBoxProceedure);



        // A non-subclassed edit box.
        hNORMAL_TEXT1 = CreateWindowExW(
            WS_EX_CLIENTEDGE,
            L"edit",
            L"EDIT BOX\r\nNORMAL (NOT SUBCLASSED)\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30",
            WS_CHILD | ES_MULTILINE | WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL,
            350, 10,
            300, 400,
            hwnd,
            (HMENU) IDB_NORMAL_TEXT,
            GetModuleHandle( nullptr ),
            nullptr
            );


        }
        break;


        case WM_CLOSE:
        {
            DestroyWindow(hwnd);
        }
        break;

        case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;

        default:
        {
            return DefWindowProc(hwnd,msg,wParam,lParam);
        }
        break;

    }
    return 0;
}

LRESULT CALLBACK SubclassedEditBoxProceedure(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {

    switch(iMessage) {

        case WM_KEYDOWN: {
//            if (wParam == VK_DOWN)
            if (wParam == VK_RIGHT)
            {
               // I think that the answer goes here but I do not know how.
            }

        } break;

        default: {
            return CallWindowProc((WNDPROC)(LONG_PTR)g_iResult, hWnd, iMessage, wParam, lParam);
        } break;

    }

    return 0;

}


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{

    WNDCLASSEX  wc;
    HWND        hwnd;
    MSG         msg;

    wc.cbClsExtra = 0;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.hCursor = LoadCursor(nullptr,IDC_ARROW);
    wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc =  WndProc;
    wc.lpszClassName = g_szClassName;
    wc.lpszMenuName = nullptr;
    wc.style = 0;

    if(!RegisterClassEx(&wc))
    {
        MessageBox(nullptr, L"Window Registration Failed!", L"Error!",
        MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }


    hwnd = CreateWindowExW(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        L"Main Test Window",
        WS_OVERLAPPEDWINDOW,
        20, 20, 700, 500,
        nullptr, nullptr, hInstance, nullptr);

    if(hwnd == NULL)
    {
        MessageBox(nullptr, L"Window Creation Failed!", L"Error!",
        MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, nullptr, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}


Thank you.

Last edited on
That did not help me. I am not faulting you or Microsoft. I am saying that is not the answer. I need an answer that works.



If I simply remove the following from SubclassedEditBoxProceedure the keyboard up and down keys work for the subclassed window.
1
2
3
4
5
6
7
8
        case WM_KEYDOWN: {
//            if (wParam == VK_DOWN)
            if (wParam == VK_RIGHT)
            {
               // I think that the answer goes here but I do not know how.
            }

        } break;


That is not good enough. I want to be able to work with the subclassed window, not ignore it in its subclassed state.




But, I tried what you suggested and it did not work for me.

I added
1
2
3
4
5
HCURSOR hCurs1, hCurs2;    // cursor handles

POINT pt;                  // cursor location
RECT rc;                   // client area coordinates
static int repeat = 1;     // repeat key counter 


Then,


If I put the following into the WndProc it works, but as I stated earlier, it is not necessary.

If I put the following into the SubclassedEditBoxProceedure it does not work. And then the up and down and left and right arrow keys for the subclassed window do not work at all in the subclassed window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    case WM_KEYDOWN:

        if (wParam != VK_LEFT && wParam != VK_RIGHT &&
        wParam != VK_UP && wParam != VK_DOWN)
        {
            break;
        }

        GetCursorPos(&pt);

        // Convert screen coordinates to client coordinates.

        ScreenToClient(hwnd, &pt);

        switch (wParam)
        {
        // Move the cursor to reflect which
        // arrow keys are pressed.

            case VK_LEFT:               // left arrow
                pt.x -= repeat;
                break;

            case VK_RIGHT:              // right arrow
                pt.x += repeat;
                break;

            case VK_UP:                 // up arrow
                pt.y -= repeat;
                break;

            case VK_DOWN:               // down arrow
                pt.y += repeat;
                break;

            default:
                return 0;
        }

        repeat++;           // Increment repeat count.

        // Keep the cursor in the client area.

        GetClientRect(hwnd, &rc);

        if (pt.x >= rc.right)
        {
            pt.x = rc.right - 1;
        }
        else
        {
            if (pt.x < rc.left)
            {
                pt.x = rc.left;
            }
        }

        if (pt.y >= rc.bottom)
            pt.y = rc.bottom - 1;
        else
            if (pt.y < rc.top)
                pt.y = rc.top;

        // Convert client coordinates to screen coordinates.

        ClientToScreen(hwnd, &pt);
        SetCursorPos(pt.x, pt.y);
        return 0;


    case WM_KEYUP:

        repeat = 1;            // Clear repeat count.
        return 0;




Could it be that I am subclassing wrong? Would someone that is an expert at subclassing look at this and see if the problem is how I am subclassing and tell me how to fix that if it is?


Could it be that I am supposed to do this in the WndProc and not do this in the SubclassedEditBoxProceedure, and somehow tell the WndProc that I am working with the subclassed window? Help !




Thank you JLBorges for your attempt to help.


Update,


I tried something to test if my subclassing was working:

I added this to my SubclassedEditBoxProceedure and it works by beeping when I press a key including the up and down arrow keys.

1
2
case WM_KEYDOWN:
    MessageBeep(0xFFFFFFFF);



Could it be that I am doing this right and not understanding what I am working with?

Help !

Last edited on
Topic archived. No new replies allowed.