为什么 WS_TABSTOP 对 rich edit 控件不起作用?
Why WS_TABSTOP doesn't work on rich edit control?
使用 Tab 键更改焦点在 Rich Edit 控件上不起作用,但如果将 Rich Edit 控件替换为 WC_EDIT
控件,则可以正常工作。
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = NULL;
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W", // Works fine if replaced by WC_EDIT.
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button1 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button1",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
200,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button2 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button2",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
350,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
修改 Rich Edit 控件的 WM_GETDLGCODE
return 值。
DLGC_WANTTAB
标志和 VK_TAB
键的 DLGC_WANTMESSAGE
标志需要从 return 值中删除。
此解决方案基于 Raymond Chen 的以下 MSDN 文章:Those who do not understand the dialog manager are doomed to reimplement it, badly。
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RichEditProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC richEditOrigProc;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON)LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = NULL;
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W",
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
richEditOrigProc = (WNDPROC) SetWindowLongPtr(richEditControl, GWLP_WNDPROC, (LONG_PTR) RichEditProc);
HWND button1 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button1",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
200,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button2 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button2",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
350,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK RichEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_GETDLGCODE:
{
// THIS IS THE IMPORTANT PART
// ***********************************
LRESULT lres = CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
lres &= ~DLGC_WANTTAB;
if (lParam && ((MSG *)lParam)->message == WM_KEYDOWN && ((MSG *)lParam)->wParam == VK_TAB) {
lres &= ~DLGC_WANTMESSAGE;
}
return lres;
// ***********************************
}
break;
}
return CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
}**
使用 Tab 键更改焦点在 Rich Edit 控件上不起作用,但如果将 Rich Edit 控件替换为 WC_EDIT
控件,则可以正常工作。
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = NULL;
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W", // Works fine if replaced by WC_EDIT.
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button1 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button1",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
200,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button2 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button2",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
350,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
修改 Rich Edit 控件的 WM_GETDLGCODE
return 值。
DLGC_WANTTAB
标志和 VK_TAB
键的 DLGC_WANTMESSAGE
标志需要从 return 值中删除。
此解决方案基于 Raymond Chen 的以下 MSDN 文章:Those who do not understand the dialog manager are doomed to reimplement it, badly。
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RichEditProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC richEditOrigProc;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON)LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = NULL;
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W",
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
richEditOrigProc = (WNDPROC) SetWindowLongPtr(richEditControl, GWLP_WNDPROC, (LONG_PTR) RichEditProc);
HWND button1 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button1",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
200,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
HWND button2 = CreateWindowEx(
NULL,
WC_BUTTON,
"Button2",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
350,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK RichEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_GETDLGCODE:
{
// THIS IS THE IMPORTANT PART
// ***********************************
LRESULT lres = CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
lres &= ~DLGC_WANTTAB;
if (lParam && ((MSG *)lParam)->message == WM_KEYDOWN && ((MSG *)lParam)->wParam == VK_TAB) {
lres &= ~DLGC_WANTMESSAGE;
}
return lres;
// ***********************************
}
break;
}
return CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
}**