createthread MFC dialog based app (Syntax) - c++

I am trying to create a Worker thread but I have not done Visual C++ since 2004 and threading syntax has changed (Please don't worry about timing issues, I will have that covered). the issue is that in an MFC dialog app, every way I know of trying to create a thread won't get past the compiler. I also have tried the "&" trick. It can't seem to find this function at all. Can anyone help please? NOTE: I tried three methods and I left the first uncommented.
if (i_found >= 0) { //this is just a combobox snippet to show the calls
MessageBox(wch.GetBuffer(0), L"Port Select", MB_OK);
_serialPort->Close();
ConversationRight = gcnew Conversation(systrName);
_beginthread(&CDLP_Printer_ControlDlg::Mine_QL, 0, 0); //NONE WORKING!!
//unsigned long lpRecvThread = _beginthreadex(NULL, 0, Mine_QL, (void*)this, NULL, NULL);
//unsigned long lpThreadIdRequest;
//::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Mine_QL, (void*)NULL, 0, &lpThreadIdRequest);
}
else
MessageBox(L"Not the left board", L"Port Select", MB_OK);
_serialPort->Close();
}
void CDLP_Printer_ControlDlg::OnBnClickedBtnStop()
{
ConversationRight->WriteLn("5");
}
bool CDLP_Printer_ControlDlg::UpdateCommsWindow_left(String^ strCommsLine)
{
return false;
}
void CDLP_Printer_ControlDlg::Mine_QL()
{
//_endthread();
}

Related

RegisterHotKey() not detecting keypress

So, I am trying to write a program that detects when the keycombination Control + C is pressed, I have read that the best way to do this is to use RegisterHotKey(). I have never used this before though so I am a little confused since my code isnt working. This is the solution I found online but it doesn't work. I have looked at the documentation but that hasn't helped either. this is my code:
AutoClicker::AutoClicker()
{
clicker = std::thread(&AutoClicker::Clicker, this);
enum {KEY_C = 1};
RegisterHotKey(0, KEY_C, MOD_CONTROL, 0x5A);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) {
PeekMessage(&msg, NULL, 0, 0, 0);
switch (msg.message)
{
case WM_HOTKEY:
if (msg.wParam == KEY_C)
{
printf("1 Pressed");
}
}
}
}

EnableWindow(hWnd, false) doesn't disable keyboard input

I am attempting to disable a window under certain conditions using EnableWindow(hWnd, false);
According to the documentation, this should "disable mouse and keyboard input to the specified window".
The problem I am seeing is that it does, in fact, disable like it says, except if the cursor is currently inside of a text box in the window and the window has the focus that does not get disabled. I was thinking of doing some sort of code to take the focus off of the window as well.
Is there a better way to go about this?
Note: The window being disabled is a binary ran via _spawnl().
I'm not sure if this is a Windows feature or a bug. Either way, disabling the foreground window is not a good idea.
If you are able to modify the program you start with _spawnl() then that is a better solution. You could make it respond to WM_APP or something like that when you need to control it.
If it is a 3rd-party application then you are left with hacks.
You could try to change the foreground window with SetForegroundWindow but this will only work if you do it very soon after _spawnl() before your thread loses the foreground lock. Using LockSetForegroundWindow before _spawnl() might be able to help you keep the lock longer. There are also various other hacks to change the foreground with AttachThreadInput etc.
If you don't want to change the foreground I was able to come up with a workaround:
ShellExecute(NULL, NULL, TEXT("Notepad"), NULL, NULL, SW_SHOW);
Sleep(2000);
HWND hNP = FindWindow(TEXT("Notepad"), NULL);
Sleep(2000); // Start typing in Notepad now...
if (hNP)
{
DWORD tid = GetWindowThreadProcessId(hNP, NULL);
GUITHREADINFO gti;
gti.cbSize = sizeof(gti);
if (tid && GetGUIThreadInfo(tid, &gti))
{
HWND hChild = NULL;
if (gti.hwndFocus != hNP && gti.hwndFocus)
{
EnableWindow(hChild = gti.hwndFocus, false);
}
if (GetForegroundWindow() == hNP)
{
SendNotifyMessage(hNP, WM_ACTIVATE, WA_INACTIVE, NULL);
SendNotifyMessage(hNP, WM_ACTIVATE, WA_ACTIVE, NULL);
SendNotifyMessage(hNP, WM_SETFOCUS, NULL, NULL);
// SendNotifyMessage(hNP, WM_NCACTIVATE, false, NULL); // Uncomment to make it look like it is inactive
}
EnableWindow(hNP, false);
if (hChild)
{
EnableWindow(hChild, true);
}
}
MessageBox(NULL, TEXT("Done?"), NULL, MB_TOPMOST);
SetForegroundWindow(hNP);
PostMessage(hNP, WM_CLOSE, 0, 0);
}
This is certainly not optimal, it leaves Notepad in a state where it looks like it is enabled but it is really not. The idea is to disable the focused child window and trigger a fake activation change and forcing the focus to change. It might not work with other applications, who knows.
If you are willing to risk a deadlock you can do this instead:
DWORD tid = GetWindowThreadProcessId(hNP, NULL);
GUITHREADINFO gti;
gti.cbSize = sizeof(gti);
if (tid && GetGUIThreadInfo(tid, &gti))
{
if (GetForegroundWindow() == hNP)
{
if (AttachThreadInput(GetCurrentThreadId(), tid, true))
{
SetFocus(NULL);
AttachThreadInput(GetCurrentThreadId(), tid, false);
}
}
EnableWindow(hNP, false);
}

C++ CreateWindow: button position gets offset at window maximize

I have a weird problem over here. I created a DLL proxy for Spotify so I can "overlay" a button onto it. Basicially, thats how it works:
DllMain
-> Creates CMain class
-> Creates CToggleButton class
-> Hooks the button onto the Spotify window
It has two methods, one static one which I use for the thread since threads can't call member functions, and one non-static function which gets called by the member function.
With this, I create the thread and pass an instance of the CToggleButton class via lpParam:
CreateThread(0, NULL, WindowThreadStatic, (void*)this, NULL, NULL);
Then, the WindowThreadStatic function:
DWORD WINAPI CToggleButton::WindowThreadStatic(void* lpParam)
{
return ((CToggleButton*)lpParam)->WindowThread();
}
And the main window thread function inside the class:
DWORD CToggleButton::WindowThread()
{
MSG msg;
hButton = CreateWindowA("BUTTON", "Test", (WS_VISIBLE | WS_CHILD), 0, 0, 100, 20, parenthWnd, NULL, hInst, NULL);
bool bQueueRunning = true;
while (bQueueRunning)
{
if (PeekMessage(&msg, parenthWnd, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_QUIT:
bQueueRunning = false;
break;
case WM_LBUTTONDOWN:
if (msg.hwnd == hButton)
{
MessageBoxA(parenthWnd, "Button!", "Button", MB_OK);
continue;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
}
return 0;
}
As you can see, this also contains the message loop for the button (I didn't use GetMessage() here because it was very unresponsive so I decided to use PeekMessage() together with a 10ms delay, which works fine.)
Little picture to show how it looks like:
All great, but if I maximize the window, the button disappears. When I minimize and maximize the window a few times, the button can be seen again, but with very weird coordinates (not the original 0,0 I gave him).
So what is my problem here? Why do the coordinates get offset?
Thanks for reading my long post :)

How to reorder windows in an application in MFC

Let's say that there are several different Windows (CWnd) open in a software, and the pointers to all active windows are saved in std::vector<Node> tabsInfo. Here is a portion of code for Node:
struct typedef Node {
...
CWnd *pWnd;
...
}
I have a handler to update the Z-order of all active windows using tabsInfo, which looks like this:
for (size_t i = tabsInfo.size(); i > 1; i--) {
Node *pN_cur = &tabsInfo.at(i - 1);
Node *pN_next = &tabsInfo.at(i - 2);
ret = pN_cur->pWnd->SetWindowPos(pN_next->pWnd, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
ASSERT(ret != 0); // Sanity check
}
However, when I debug them, even though they run without error, it makes no changes to the ordering of all windows.
Am I misunderstanding on how to use SetWindowPos?
When I looked other questions answered (which deals with buttons inside dialogs instead of windows), they gave the similar solution, but it doesn't seem to work here.
For anyone who have the same problem, I added a few more lines, and it worked:
for (int i = tabsInfo.size() - 1; i >= 0; i--) {
Window_Node *pWN = &tabsInfo.at(i);
if (tabsInfo.at(i).checked) { // Ignore this line. This is program-specific
WINDOWPLACEMENT wp = {};
wp.length = sizeof(WINDOWPLACEMENT);
pWN->pWnd->GetParentFrame()->GetWindowPlacement(&wp);
wp.showCmd=SW_RESTORE;
pWN->pWnd->GetParentFrame()->SetWindowPlacement(&wp);
ret = pWN->pWnd->GetParentFrame()->SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
ASSERT (ret != 0);
} else {
pWN->pWnd->GetParentFrame()->ShowWindow(SW_MINIMIZE);
}
}
}
Hope it helps someone :)

Win32 ReleaseDC and DestroyWindow returning 0

I have a single window created with the CS_OWNDC style for an engine I'm coding and it's showing properly, but when I'm closing the program and I call the ReleaseDC(hWnd, hDC) the function returns 0 always (and according to MSDN it means it couldn't be released).
The DestroyWindow(hWnd) is also returning 0.
I am calling GetDC(hWnd) during the window creation.
What is weird is that I only get this error if I pass through the messaging function, even if it has nothing coded inside.
My main code is looking like this:
WindowManager windowManager;
HWND mainWindow = windowManager.Initialize("Title", "ClassName", 1024, 768, 32, WindowProc);
MSG msg;
while(true)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) { break; }
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
windowManager.Clear(); //this calls ReleaseDC(hWnd, DC) and DestroyWindow(hWnd) among other release codes
What I don't understand is that if I comment the whole while loop, I don't get the release or destroy window errors.
Calling GetLastError() gives me a 0 too.
On MSDN it says the DestroyWindow must be called from the same thread, but I'm not coding any multi thread functions so I don't think that's the case.
What could be causing this?