Can't Send custom message from one control to another - c++

I have a situation here and i don't know what is wrong.
I have a parent and 2 sunclassed children.Both are edit types.
Now i am using the first control(first child) to get input from the user and it all works fine,
then i send a message to the parent through a custom message and than i want to forward the message to the second control yet when i use
SendMessage();
nothing happends....
my custom message is defined like this :
#define WM_USERMESSAGE 0x0401
Another question i have is how do i send strings? 'cause when i send the message to the father
through lParam it says its value is 72 but i dont see any refrence to my text that i have sent.
these are the code segments:
child 1 sending message to father after getting input:
case WM_KEYUP:
{
switch (wParam) {
case VK_RETURN:
{
length = GetWindowTextLength(hwnd);
GetWindowText(hwnd, buf,length);
SetWindowText(hwnd,NULL);
tempa = SendMessage(GetParent(hwnd), WM_USERMESSAGE,sizeof(buf),*buf);
return 0;
}
}
return 0;
}
Father gets message and trys to forward it:
case WM_USERMESSAGE:
{
int tempb = SendMessage(nhwnd, WM_USERMESSAGE, wParam, (LPARAM)"Hi");
}
and the child number 2 is listening for the message:
case WM_USERMESSAGE:
{
SetWindowText(window, "hi");//(TCHAR*)lParam);
return 0;
}
(now as you see i used static strings to check if the functions work but i want to change them so i could recive information from the messages)
Thanks for the help in advance!

Your initial SendMessage() from the first edit to the parent window is not sending the string data correctly. You are dereferencing your buffer pointer, so you are only sending the first character (72 is the ASCII 'H' character). You need to get rid of that dereference and pass the buffer pointer as-is. And if you are going to send the buffer length (which you don't use), you need to send the length that GetWindowText() returns, not the full size of your buffer, so the receiver knows exactly how many characters are actually in the buffer.
Try this:
case WM_KEYUP:
{
switch (wParam)
{
case VK_RETURN:
{
ZeroMemory(buf, sizeof(buf));
length = GetWindowTextLength(hwnd);
if (length > 0)
length = GetWindowText(hwnd, buf, min(length+1, sizeof(buf)));
SetWindowText(hwnd, NULL);
tempa = SendMessage(GetParent(hwnd), WM_USERMESSAGE, length, (LPARAM)buf);
return 0;
}
}
return 0;
}
.
case WM_USERMESSAGE:
{
int tempb = SendMessage(nhwnd, WM_USERMESSAGE, wParam, lParam);
return 0;
}
.
case WM_USERMESSAGE:
{
SetWindowText(window, (LPTSTR)lParam);
return 0;
}
Assuming all of your HWNDs are valid, then the forwarding should work fine. If the message is not making it all of the way, then one of your HWNDs is not valid.

Related

How do you write an IsPressed (a function that should only return true on first press)?

I need a function in a game loop that should only return true on first press.
I don't know which game I can give an example from which game is currently on the market, but I will explain this request in detail (I haven't played/can't play any of the modern games because I'm blind).
For example, there is an event you are listening to in the loop. When the user presses the S key, a text showing the last status of the character appears on the screen: Stamina, energy etc.
This loop can run thousands of times per second, as the loops depend on the speed of the hardware and the code you write.
We only need to detect the first press of the user. It should return false when the key is hold pressed. Otherwise, the last status of the user is shown thousands of times on the screen.
I am trying to provide this functionality using win32api. GetAsyncKeyState seems like the right option for this scenario but I don't understand how this can be done.
bool IsPressed(int key) {
return GetAsyncKeyState(key) & 1 != 0;
}
The function I wrote acts like a char event.
How can I write this?
I tried using other answers on StackOwerflow. However, I could not find an answer to the question I asked. Still, these answers helped me with some issues:
What is the fastest way to determine a key press and key holding in Win32?
While the GetAsyncKeyState can indicate via least significant bit whether the key has been pressed since the last call to this function, this behavior cannot be relied on.
If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior...
Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the preemptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application.
Therefore, you can't rely on the Windows API to do the bookkeeping for you. I suggest wrapping any key queries in a class that you'll use for any button presses.
class KeyInput {
public:
using key_type = int;
enum class Transition {
none,
pressed,
released,
};
struct PressResult {
bool pressed;
Transition transition;
};
PressResult state(key_type key) {
PressResult result;
result.pressed = (GetAsyncKeyState(key) < 0);
if (auto it = last_states_.find(key); it != last_states_.end()) {
if (last_states_[key] == result.pressed) {
result.transition = Transition::none;
}
else if (result.pressed) {
result.transition = Transition::pressed;
}
else {
result.transition = Transition::released;
}
}
else {
result.transition = Transition::none;
}
last_states_[key] = result.pressed;
return result;
};
private:
std::unordered_map<key_type, bool> last_states_{};
};
See it in action
Note
This will not capture transitions since the last iteration of your program. In order to handle that, you'll need your class to check every button press (that you care about) on every iteration.
After working on it a more, I realized that I cannot do this with GetAsyncKeyState or a similar function. I wrote something simple using Windows' callback and event system.
I didn't care about data race and other issues. You probably need to use a mutex but that depends on your code.
The code below keeps the state of the keys in an array. Changes are sent to the array with a function by the callback.
If you compile the program in console mode, you will see that it is printed to the console only once when you press A. It was exactly what I was looking for.
To compile you can use:
g++ minimal.cpp
You can press a to test it on a standard querty keyboard.
#include <iostream>
#include <windows.h>
#include <vector>
// We define a struct that holds the key state.
// firstPress will be updated by IsPressed.
struct keyState {
bool firstPress;
bool down;
};
// We have an Array-based collection of keys. Changes will be made by callback.
std::vector<keyState> allKeyStates(256);
void keyProcess(unsigned short key, bool down)
{
if(down) {
if(!allKeyStates[key].down) {
allKeyStates[key].down = true;
allKeyStates[key].firstPress = true;
}
return;
}
allKeyStates[key].down = false;
allKeyStates[key].firstPress = false;
}
bool IsPressed(unsigned short key)
{
if(allKeyStates[key].firstPress) {
allKeyStates[key].firstPress = false;
return true;
}
return false;
}
// forward decleration
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int main()
{
MSG msg = {0};
HWND handle;
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = "mini_windows_test";
if( !RegisterClass(&wc) )
return -1;
handle = CreateWindow(wc.lpszClassName, "Minimal Key handling application", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0, 640, 480, 0, 0, GetModuleHandle(NULL), NULL);
if(handle == NULL)
return -1;
while(GetMessage(&msg, NULL, 0, 0 ) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if(IsPressed(0x41)) {
std::cout << "Key A: it will only be print on the first press. Holding the key will not run repeatedly.\n";
}
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case WM_KEYDOWN:
keyProcess((unsigned short)wParam, true);
break;
case WM_KEYUP:
keyProcess((unsigned short)wParam, false);
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Apologize for the bady English and typos. You can edit my question and my answer if it works for you.
I do not know about C ++, but it certainly follows the same process in all languages, so you can set that pressure method to "if" and define a number that, by pressing its value, becomes one, And write. In "If" if the value of the number is equal to 1, do not do this again
In java, for example, it says:
int x = 0;
Button back = findViewById(R.id.button);
if(x == 0){
back.setOnClickListener(v -> {
//your code to do;
x = 1;
});
}else{}
that work in C++ too,

How to add mouse double click to ListBox

To this code: https://www.dreamincode.net/forums/topic/163804-microsoft-working-with-listboxes-part-i/
It is displaying list and looping nicely.
Sadly my guru never finished his code.
So plan would be adding double click detection on a name. How?
case WM_COMMAND:
{
return 0;
}
Something like this? 11 is this child window where names are.
case WM_COMMAND:
{
if (LOWORD(wparam) == 11) {
if ((message) == LBN_DBLCLK) {
cout << "double click" << endl;
}
}
return 0;
}
Doesn't work
First, according to the documentation:
Parameters
wParam
The LOWORD contains the identifier of the list box. The HIWORD specifies the notification code.
lParam
Handle to the list box.
Remarks
This notification code is sent only by a list box that has the LBS_NOTIFY style.
So in the first step you need to add this style and use HIWORD (wParam) to determine whether to double-click the list.
Then if you need to get the elements of the list, you should not send LB_GETCURSEL to window_handle, but should send it to This->listbox_handle, which is the window handle of the listbox. Then you can get it by sending LB_GETTEXT Text content.
Here is the code:
case WM_COMMAND:
{
if (HIWORD(wparam) == LBN_DBLCLK) {
TCHAR temp[100]{};
int index = SendMessageW(This->listbox_handle, LB_GETCURSEL, 0, 0L);
SendMessageW(This->listbox_handle, LB_GETTEXT, index, (LPARAM)temp);
MessageBox(window_handle, temp, L"test", 0);
}
return 0;
}
And it works for me:
Try replacing:
if ((message) == LBN_DBLCLK)
with:
if (HIWORD (wParam) == LBN_DBLCLK)
Documentation here.

Receiving wParam from message received from DLL

I'm working on a program that needs to work with an imported DLL. I can load the DLL, and execute functions within it fine.
The problem comes up when I need to extract data it has sent with Send/PostMessage.
The documentation says:
MSG_PSKCHARRDY
Numeric Value is WM_USER+1001 or 0x400+0x3E9 or 0x7E9 or 2025.
This message is sent from the DLL to the Window whose handle is passed when the fnStartSoundCard is called. It is sent whenever there is an ASCII character available from the receiver or if in the Transmit mode, when a character has been sent out the soundcard.
The following parameters are sent along with this message:
wParam = The ASCII character(0 to 255)
lParam = -1 if is a transmitted character, or the Receive channel number(0-49) that is sending the message.
I've added this as a case under my WindProc as case: WM_USER + 1001: and any code underneath is executed when the fnStartSoundCard function is called, so I know it's receiving the message.
But when I try to print the wParam as a char string, I always get an exception thrown at the end of my DispatchMessage(&msg) function here:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
Exception thrown at 0x76524463 (ucrtbase.dll) in PSK31.exe:
0xC0000005: Access violation reading location 0x0000004D.
My message handler looks like this:
case WM_USER + 1001:
if (hWnd == GetActiveWindow()) {
char textChar;
SOMETHING = (char*)wParam;
printf(SOMETHING);
Sleep(1000);
}
break;
How can I get the char extracted from the message?
There are two mistakes in your code.
The documentation you quote clearly says that the MSG_DATARDY message is defined as WM_USER+1000 but you are using WM_USER+1001 instead.
The documentation you quote does not say anything about the message's wParam and lParam values being pointers to strings, but you are trying to treat the wParam as if it were, and it is clearly not. Your code is crashing trying to read from address 0x0000004D, which is a memory address reserved by the OS, so wParam can't be a pointer to data in application-accessible memory. 0x4D (77) is a small number, certainly small enough to look like the actual frequency number, so the numeric values of wParam and lParam should be used as-is, not casted to string pointers.
Try this instead:
#define MSG_DATARDY (WM_USER + 1000)
case MSG_DATARDY:
if (hWnd == GetActiveWindow()) {
int freq = (int) wParam;
int strength = (int) lParam;
printf("RX frequency: %d Hz, signal strength: %d", freq, strength);
Sleep(1000);
}
break;
UPDATE: in leau of the updated documentation you quoted, you are still making the same mistake regarding the wParam. It is NOT a pointer to an ASCII character. It is the actual character instead, so use the value as-is:
#define MSG_PSKCHARRDY (WM_USER + 1001)
case MSG_PSKCHARRDY:
if (hWnd == GetActiveWindow()) {
char textChar = (char) wParam;
int channel = (int) lParam;
if (channel == - 1) {
printf("TX character: %c", textChar);
}
else {
printf("RX channel: %d, character: %c, ", channel, textChar);
}
Sleep(1000);
}
break;

GetKeyboardState one key delay

I'm working on ToUnicodeEx function and it requires keyboard state as the input parameter. So, I used the GetKeyboardState function to do that. But I noticed when I'm typing key combinations with modifier keys like SHIFT+A there is one character delay. Here is the example.
aaa (holding SHIFT now) aAAAAAAA (release SHIFT) Aaaa
While I was debugging this I noticed GetKeyboardState is causing this delay. How can I handle or prevent this delay?
Here is my whole keyboard hook proc.
void proc(KBDLLHOOKSTRUCT kbdStruct) {
fdebug = fopen("debug.txt", "a");
foutput= fopen("output.txt", "a");
WCHAR pwszBuff[9];
WCHAR key[9];
char str[8];
BOOL isDead = FALSE;
BYTE lpKeyState[256];
HWND currentHwnd = GetForegroundWindow();
LPDWORD currentProcessID = 0;
DWORD currentWindowThreadID = GetWindowThreadProcessId(currentHwnd, currentProcessID);
DWORD thisProgramThreadId = GetCurrentThreadId();
hkl = GetKeyboardLayout(thisProgramThreadId);
if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, TRUE))
{
GetKeyboardState(lpKeyState);
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, FALSE);
}
else
{
GetKeyboardState(lpKeyState);
}
int ret = ToUnicodeEx(kbdStruct.vkCode, kbdStruct.scanCode, lpKeyState, pwszBuff, 8, 0, hkl);
fprintf(fdebug, "vkCode: %d\n", (int)kbdStruct.vkCode);
fprintf(fdebug, "ret: %d\n", (int)ret);
fprintf(fdebug, "lastIsDead: %d\n", (int)lastIsDead);
fprintf(fdebug, "lastIsMod: %d\n", (int)lastIsMod);
fprintf(fdebug, "lastVKCode: %d\n", (int)lastVKCode);
if (ret == -1) {
isDead = TRUE;
ClearKeyboardBuffer(kbdStruct.vkCode, kbdStruct.scanCode, hkl);
}
else if (ret == 0) {
}
else {
memcpy(&key, &pwszBuff, sizeof(pwszBuff));
WideCharToMultiByte(CP_UTF8, 0, key, -1, str, sizeof(str), NULL, NULL);
fprintf(fdebug, "str: %s\n", str);
}
if (lastVKCode != 0 && lastIsDead == TRUE) {
ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, pwszBuff, 4, 0, hkl);
memcpy(&key, &pwszBuff, sizeof(pwszBuff));
WideCharToMultiByte(CP_UTF8, 0, key, -1, str, sizeof(str), NULL, NULL);
fprintf(fdebug, "str: %s\n", str);
lastVKCode = 0;
}
fprintf(fdebug, "%s", "---------------------------------------------------\n");
fprintf(foutput, "LSHIFT: %d\n", (int)lpKeyState[160]);
fprintf(foutput, "RSHIFT: %d\n", (int)lpKeyState[161]);
fprintf(foutput, "%s", "---------------------------------------------------\n\n");
lastVKCode = kbdStruct.vkCode;
lastScanCode = kbdStruct.scanCode;
lastIsDead = isDead;
fclose(fdebug);
fclose(foutput);
}
Here is updated version of hookcallback thanks for Ton Plooij. But still, I have the same problem.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = CallNextHookEx(_hook, nCode, wParam, lParam);
if (nCode >= 0)
{
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
hookStruct = *((KBDLLHOOKSTRUCT*)lParam);
proc(hookStruct);
}
}
return ret;
}
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, FALSE);
This does not do what you hope it does. Sometimes. It is a valiant and necessary effort to get the proper values when you call GetKeyboardState(). Took me a while to find the failure mode, it wasn't obvious at all and I could not get the code to fail the same way. It works just fine when a GUI process is in the foreground, try it with Notepad or VS for example.
But not when it is a console mode process.
Explaining that is a bit convoluted, it is actually GetWindowThreadProcessId() that returns misleading information. It tries too hard to keep up the illusion that it is the console process that owns the console window. It doesn't, it is actually the associated conhost.exe process that owns it. It was csrss.exe on old Windows versions, conhost.exe was added in Windows 7 to solve the drag+drop issues caused by UIPI (aka UAC).
But without any decent way to discover the specific conhost.exe process that owns the window, let alone the thread id. The subject of this Q+A. Pretty doubtful it is going to help you.
Only decent advice is the well-known unpleasant one: if you need to reliably translate keystrokes then you need to use a WH_KEYBOARD hook instead of WH_KEYBOARD_LL. So GetKeyboardState() is always accurate, the hook callback runs in-process.
A LowLevelKeyboardProc receives WM_KEYUP and WM_KEYDOWN messages in its wParam. You could simply keep track of pressed modifier keys yourself, in this case to detect shift down and up. Store the key state information in a static variable and use this to test if shift is pressed while processing other keys instead of using GetKeyState.
You can try GetAsyncKeyState().
This function in my keyboard hook module work perfectly.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx
It seems that this function can catch hardware interrupt when you press keys.
And your GetKeyboardState has something to do with the Windows Registry.
It seems to have something to do with belows:
“HKEY_USERS\DEFAULT\ControlPanel\Keyboard”,Modify “KeyboardDelay” value to 0(default 1)
And change “KeyboardSpeed” value to 48(dafault 31).
According to Hans Passant's answer I searched for how can I get correct value from GetWindowThreadProcessId() and succeeded with instead of getting hWnd and windowThreadID every time in hook callback, I get these values to global variable just after program start and used variables in hook callback.

RDP connection hook called twice for every connection

I want my application to hook remote connect and disconnect events for all sessions on the specified computer.
According to the documentation, I should call WTSRegisterSessionNotification function first:
WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_ALL_SESSIONS);
Then in the messages processor callback I should do the required stuff on WM_WTSSESSION_CHANGE message type:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WTSSESSION_CHANGE:
{
// do stuff
break;
}
}
}
It works very strange however. Every time I connect or disconnect to/from the computer where my application running, WTS_REMOTE_CONNECT or WTS_REMOTE_DISCONNECT called twice -- in one of these calls I can get user name and in another I can't (it's just an empty string).
case WM_WTSSESSION_CHANGE:
{
const int reason = (int)wParam;
const DWORD sessionId = (DWORD)lParam;
switch (reason)
{
case WTS_REMOTE_CONNECT:
{
DWORD bytesReturned = 0;
LPSTR pData = NULL;
if (WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pData, &bytesReturned) == 0)
{
// Handle error
break;
}
const std::string username = pData;
WTSFreeMemory(pData);
// do other stuff
I found this question but it has very strange accepted answer:
Hmm, the answer appears to be that it's fairly normal for these fields
to be empty on a terminal services/RDP session
I don't understand why it actually works this way.