I have a multiline Edit control that allow to multiline text from other source (i.e copy/paste,...) but I don't want to allow user have new line by press Enter key directly.
How can I handle Enter key in this case? Thank!
You can do this with a simple sub-class of the edit control that blocks the return key:
LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
if (uMsg == WM_CHAR && wParam == VK_RETURN)
return 0;
LRESULT lRes = DefSubclassProc(hWnd, uMsg, wParam, lParam);
if (uMsg == WM_DESTROY)
RemoveWindowSubclass(hWnd, EditSubclassProc, 0);
return lRes;
}
To invoke it:
SetWindowSubclass(hWndEdit, EditSubclassProc, 0, 0);
Related
I have a window with no controls with WS_EX_ACCEPTFILES enabled and the event triggers successfully when dragging files from explorer. What I need to do is extract the files to a vector. From what I've read, the wParam is supposed to contain the location of the files within a DROPFILES struct but I don't know how to access them.
LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR
uIdSubclass, DWORD_PTR dwRefData)
{
if (uMsg == WM_DROPFILES)
{
// extract files here
vector<string> files;
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
I don't need to send them to any controls since my window is for an openGL application, I just need to retain them in a list, how can it be done?
Per the WM_DROPFILES documentation:
Parameters
hDrop
A handle to an internal structure describing the dropped files. Pass this handle to DragFinish, DragQueryFile, or DragQueryPoint() to retrieve information about the dropped files.
lParam
Must be zero.
Simply type-cast the wParam to HDROP and call the drag-drop functions as needed, eg:
LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
if (uMsg == WM_DROPFILES)
{
HDROP hDrop = reinterpret_cast<HDROP>(wParam);
// extract files here
vector<string> files;
char filename[MAX_PATH];
UINT count = DragQueryFileA(hDrop, -1, NULL, 0);
for(UINT i = 0; i < count; ++i)
{
if (DragQueryFileA(hDrop, i, filename, MAX_PATH))
files.push_back(filename);
}
DragFinish(hDrop);
return 0;
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
Alternatively:
LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
if (uMsg == WM_DROPFILES)
{
HDROP hDrop = reinterpret_cast<HDROP>(wParam);
// extract files here
vector<string> files;
string filename;
UINT count = DragQueryFileA(hDrop, -1, NULL, 0);
for(UINT i = 0; i < count; ++i)
{
UINT size = DragQueryFileA(hDrop, i, NULL, 0);
if (size > 0)
{
filename.resize(size);
DragQueryFileA(hDrop, i, &filename[0], size+1);
files.push_back(filename);
}
}
DragFinish(hDrop);
return 0;
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
I apologize if I'm overlooking something, but I'm trying to just create a placeholder window within an ATL dialog, which will be used to host a preview handler. I thought placing a custom control might be the thing to do, since it's blank and would occupy a designated place, but that's causing the dialog to crash, and I get the feeling doing something with a custom control is more complicated than I'm looking for. So is there a way to just put a dummy window inside a dialog for use as a host site? Thanks for any input.
Update: I seem to have achieved the desired result using a simple blank picture control. But I'm still wondering if there's a more official way of doing this.
for placeholder we need use exactly custom control. the point - need specify window class name. and this class must be registered.
let name of class will be MyClass
so in .rc file must be
CONTROL "Custom1",IDC_CUSTOM1,"MyClass",...
and we need register "MyClass", minimal code
class MyWndCls
{
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCDESTROY:
delete this;
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK _WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return reinterpret_cast<MyWndCls*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA))->WindowProc(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK StartWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_NCCREATE)
{
if (MyWndCls* p = new MyWndCls)
{
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)p);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)_WindowProc);
return p->WindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
inline static const WCHAR clsname[] = L"MyClass";
public:
static ULONG Register()
{
WNDCLASS wndcls = {
0, StartWindowProc, 0, 0, (HINSTANCE)&__ImageBase, 0,
LoadCursorW(0, IDC_HAND), (HBRUSH)(COLOR_INFOBK + 1), 0, clsname
};
return RegisterClassW(&wndcls) ? NOERROR : GetLastError();
}
static ULONG Unregister()
{
return UnregisterClassW(clsname, (HINSTANCE)&__ImageBase) ? NOERROR : GetLastError();
}
};
of course we need call MyWndCls::Register(); before create any dialog with this custom control
I would like to hide a caret from a RichEdit(50W) with ES_READONLY style specified.
It's pretty confusing for the user, when the caret is blinking and the user can't type.
I tried to hide the caret using HideCaret() function,
however it doesn't work for me with following code:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) // Subclassed control
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
//Also tried with EN_SETFOCUS
case WM_SETFOCUS:
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
HideCaret(ChatMessages); //Returns 5 (Access denied.)
break;
}
//According the documentation:
//If your application calls HideCaret five times in a row,
//it must also call ShowCaret five times before the caret is displayed.
case WM_KILLFOCUS: //The message is called when the RichEdit get focus, however nothing happens.
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
Here is the solution:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
case WM_LBUTTONDOWN:
{
HideCaret(ChatMessages);
break;
}
case WM_KILLFOCUS:
{
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
NOTE this only works when user induces the focus with mouse. Therefore if anyone knows how to deal with it correctly, feel free to answer, I'll be glad.
I'm trying to make it so that a user can select text from a read-only edit box, but he won't see the blinking caret. I've been able to make the caret disappear from the edit, but it can still be seen for an instant.
This is my code for the subclass:
LRESULT CALLBACK UserInfoProc (HWND hUserInfoWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
HideCaret(hUserInfoWnd);
return DefSubclassProc(hUserInfoWnd, uMsg, wParam, lParam);
}
It's a modest bit of code, I know, but it almost does what I want.
So what happens is, that when I click the edit, the caret can be seen for an instant (50ms?). I want that it doesn't appear at all. How can I do this? I want the user to still be able to select the text from the edit.
You could try moving the HideCaret() call to after the DefSubclassProc(), since at the moment if a message triggers the caret it won't be until the next message that it's hidden again.
Also, I would guess that the only message that triggers the caret to be shown is WM_SETFOCUS, so you may want to test for that message only. For example,
LRESULT CALLBACK UserInfoProc (HWND hUserInfoWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
LRESULT lRes = DefSubclassProc(hUserInfoWnd, uMsg, wParam, lParam);
if (uMsg == WM_SETFOCUS) // maybe?
HideCaret(hUserInfoWnd);
return lRes;
}
I'm trying to send a duplicate message to an editbox window in this code:
extern "C" HOOK_DLL_API LRESULT CALLBACK GetMsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
{
CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
KBDLLHOOKSTRUCT *lpk = (KBDLLHOOKSTRUCT*) lParam;
ghServerWnd; // ghServerWnd == Edit1. that defined..
if (wParam == WM_KEYDOWN)
{
// case1: this code working.. but, unicode(IME character) no sent;;
SendMessageW(ghServerWnd, WM_CHAR, (WPARAM)lpk->vkCode, 0);
// case2: this code - not working.. T_T
SendMessageW(ghServerWnd, wParam, lParam, 0);
}
return CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
I need help with "case2" as marked in the code.
Thanks for reading.
Well i'm not surprised case 2 does not work. You are sending KBDLLHOOKSTRUCT as the wParam.
I would have thought.
SendMessage( ghServerWnd, wParam, (WPARAM)lpk->vkCode, (LPARAM)lpk->scanCode );
Would work better (Though I'm not 100% convinced my LPARAM is complete).