How to detect Windows suspend message? - hook

Does somebody know how to detect a Windows suspend message by C/C++ code?
Or, does SetWindowsHookEx() function do this?
Does somebody have these code for me? I want to detect this message.

If you are talking about sleep and hibernate – the answer is yes, you can. You just need to listen to WM_POWERBROADCAST message.
Suppose you have an MFC application and a window class which is a subclass of CWnd. Then you can do:
BEGIN_MESSAGE_MAP(CMyWindow, CWnd)
//{{AFX_MSG_MAP(CMyWindow)
ON_MESSAGE(WM_POWERBROADCAST, OnMsgPowerBroadcast)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
...
LRESULT CMyWindow::OnMsgPowerBroadcast(WPARAM wParam, LPARAM lParam)
{
if (wParam == PBT_APMSUSPEND) {
// The system is suspending.
}
return TRUE;
}

Related

Conditionally stopping a CPropertySheet from closing from the page OnOK button handler

I have just encountered an issue with CPropertyPage.
I have been trying to use the OnOK handler to do some validation:
void CCalendarSettingsGooglePage::OnOK()
{
bool bHandle = false;
UpdateData(TRUE);
// AJT v20.2.0 — We need to pass "true" so that the error message will display!
if (ValidSettings(true))
{
bHandle = true;
SaveSettings();
}
if (bHandle)
CMFCPropertyPage::OnOK();
}
The problem is, the sheet still closes down. I had hoped that preventing the CMFCPropertyPage::OnOK would have stopped the sheet closing. But it doesn't.
I understand from here that the sheet's OnOK is making a EndDialog(IDOK) call. But i don't want to complicate my sheet. The testing is here in this page. so I need a was for the sheet to know if it should close or not when user clicks the OK button.
You need to override the OnCommand handler of your property page's parent property sheet class and intercept the clicks for the IDOK command (which will be given in the wParam parameter). If you do not call the base class OnCommand but still return TRUE to indicate that your have handled the command, then the property sheet will not close:
BOOL MyPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
{
if (wParam == IDOK) { // OK button clicked...
if (!ValidSettings(true)) return TRUE; // NOT valid, prevent further processing.
}
// You can also intercept the "Apply" command by testing for ID_APPLY_NOW
// Everything is OK, so continue processing ...
return CMFCPropertySheet::OnCommand(wParam, lParam);
}
Note that I have assumed your parent is derived from CMFCPropertySheet, but the same works for the 'older' CPropertySheet.

How to know that a certain boost thread has been executed in boost C++?

I have made a separate thread other than the main one using boost C++ library in my source code:
boost::thread t(&initSynthesis);
I want to know when this initSyntesis() function is executed ( or the thread t) so that I can make the button visible on the windows form which was initially hidden using:
button1->show();
But the problem is that I'm making thread t from the constructor of the form class and initSynthesis function is not a part of this class so I'm unable to show the button when this function is executed. How to solve this issue?
You could pass button1 to initSynthesis, and then in initSynthesis you can call button1->show();.
Note that button1 should be passed by reference, not by value.
void initSynthesis(System::Windows::Forms::Button^% button1)
{
button1->show();
//Do something else
}
//Thread will call 'initSynthesis' with 'button1'
boost::thread t{ &initSynthesis, button1 };
Based on your comments on the other answer, it appears that you're using boost threads with C++/CLI. It would be highly appropriate to use a .Net thread instead.
Using .Net threads, the answer to your question is very similar to the other answer, except you don't need to pass the button explicitly. Thread methods in .Net are allowed to be instance methods without jumping through any extra hoops, so you can just access instance fields like normal.
public ref class MyWindow
{
Button^ button1;
void foo()
{
Thread^ t = gcnew Thread(gcnew ThreadStart(this, &MyWindow::InitSynthesis));
t->Start();
}
void InitSynthesis()
{
// Do work
// OK, work's done, show the "Next" button.
this->button1->Show();
}
}

waitForReadyRead() in subthread freezes the GUI thread

Sorry for my poor English :(
I use a class named SerialPort inherited from QObject:
serial_port.cpp & serial_port.h:
class SerialPort: public QObject{
Q_OBJECT
private:
bool checkStatusConnected();
private slots:
void readData();
}
bool SerialPort::checkStatusConnected(){
port.waitForReadyRead(200);
QBytesArray recv = port.readAll();
QString tmp = (QString)recv;
if(tmp.contains("Connected", Qt::CaseInsensitive))
return true;
return false;
}
MainWindow.cpp
void MainWindow::on_btnConn_clicked()
{
QThread* thread = new QThread(this);
serialport->moveToThread(thread);
serialport->connect();
}
In SerialPort::connect() I opened the port and send the connect command. Till now everything is ok. Due to slow speed of serial port I need to check the string return to me before next actions, so in SerialPort::connect() I call checkStatusConnected(). However, in this function waitForReadyRead() freezes the GUI thread as long as the time I set which makes me confused.
Why is the GUI thread blocked by another QThread and how to solve this problem?
Thanks!
You don't need to use threads for that. QSerialPort is event driven and works asynchronously. Use a timer to see whether you have received something within the required time.
QSerialPort port(....);
connect(&port, SIGNAL(readyRead()), this, SLOT(readFromSerialPort()));
QTimer timer;
timer.setInterVal(1000); // time you want to wait
connect(&timer, SIGNAL(timeout()), this, SLOT(handleTimeout()));
void SomeClass::readFromSerialPort()
{
QByteArray data(port.readAll());
// do somework
}
Found the examples. Check this out, this will suffice your needs I think.
http://doc.qt.io/qt-5/qtserialport-creaderasync-example.html

Scrollbar messages block interthread messages in MFC

I have an MFC application which is composed of multiple threads, but the problem is with a specific two.
The first thread (CGuiThread) is responsible for GUI (it's not the main thread) and contains a window object (CMainWindow), which contains an inner window object (CInnerWindow), which displays multiple progress displays and has a scroll bar.
The second thread (CStatusDispatcherThread) is responsible for sending to the gui thread messages, which contain progress status information related to some calculation processes.
Once the calculations begin, the status dispatcher sends messages with the status to the GUI thread. The gui thread updates progress bars in the inner window accordingly.
The problem starts when I move or hold the thumb of the inner window's scroll bar - it seems that GUI thread stops processing the status messages from the status dispatcher thread, since the progress bars are no longer updated. Not only that, I'd expect the status messages to be stopped somewhere and processed once I release the tumb, but it is not happening. New messages arrive but the messages that while clicking are lost.
If anyone has an idea what could be the cause, I would be very grateful.
I tried "catching" the status messages in the CGuiThread::PreaTranslateMessage function, but it seems that after holding the scroll thumb, they no longer get there, even though PostThreadMessage of CStatusDispatcherThread indicates they were sent successfully.
#define MY_MESSAGE 1
class CStatusDispatcherThread : public CWinThread
{
//...
// This class sends progress status percentaget to gui thread via PostThreadMessage
OnTimer(UINT nIDEvent)
{
PostThreadMessage(iThreadID,MY_MESSAGE,100,0);
}
};
class CGuiThread : public CWinThread
{
//...
BEGIN_MESSAGE_MAP(CGuiThread, CWinThread)
ON_THREAD_MESSAGE(MY_MESSAGE,OnStatusMessage)
END_MESSAGE_MAP()
private:
CMyMainWindow m_mainWindow;
void OnStatusMessage(WPARAM iStatus, LPARAM dummy);
{
m_mainWindow.updateStatus((int)iStatus)
}
};
class CMyMainWindow : public CWnd
{
//...
void updateStatus(int iStatus)
{
m_sbarWindow.updateStatusBar(iStatus);
}
private:
CInnerWindow m_sbarWindow;
};
class CInnerWindow : public CWnd
{
//...
void updateStatusBar(int iStatus)
{
//...
}
private:
BOOL Create(...)
{
CWnd::Create(strClassName, strWindowTitle, WS_DLGFRAME | WS_CHILD| WS_VISIBLE | WS_VSCROLL,
rectRectOfWnd, pParentWnd, iID, NULL);
}
void OnVScroll(nSBCode, nPos, pScrollBar)
{
//...
}
};
Thank in advance,
Gal
It is documented to fail. From the MSDN page on PostThreadMessage:
if the recipient thread is in a modal loop (as used by MessageBox or
DialogBox), the messages will be lost.
Holding down the scroll slider creates such a modal loop. You can eliminate the problem by posting to an HWND, not to a thread ID.
The only thread that is allowed to update the GUI is the main thread. Otherwise you'll end up with unpredicted behavior.

Need to know how to properly create a new object in another cpp file

I have a class. The problem now is, after a few attempt, I'm still in huge error. My problem is I don't know how to properly declare a new object for this class, inside another cpp file. I wanted to call/trigger the functions from this RebarHandler class from my other cpp file. I keep on getting problems like, 'used without being initialized', 'debug assertion failed' and so on.
In the other cpp file, I include the RebarHandler.h and did like this:
CRebarHandler *test=NULL;
test->setButtonMenu2();
When compile, I does not give any error. But, when run time, it gives error and my IE crash. I need help.
Below is the class I meant:
#pragma once
class CIEWindow;
class CRebarHandler : public CWindowImpl<CRebarHandler>{
public:
CRebarHandler(HWND hWndToolbar, CIEWindow *ieWindow);
CRebarHandler(){};
~CRebarHandler();
BEGIN_MSG_MAP(CRebarHandler)
NOTIFY_CODE_HANDLER(TBN_DROPDOWN, onNotifyDropDown)
NOTIFY_CODE_HANDLER(TBN_TOOLBARCHANGE, onNotifyToolbarChange)
NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, onNotifyCustomDraw)
NOTIFY_CODE_HANDLER(TBN_ENDADJUST, onNotifyEndAdjust)
MESSAGE_HANDLER(WM_SETREDRAW, onSetRedraw)
END_MSG_MAP()
// message handlers
LRESULT onNotifyDropDown(WPARAM wParam, LPNMHDR pNMHDR, BOOL& bHandled);
LRESULT onNotifyToolbarChange(WPARAM wParam, LPNMHDR pNMHDR, BOOL& bHandled);
LRESULT onNotifyCustomDraw(WPARAM wParam, LPNMHDR pNMHDR, BOOL& bHandled);
LRESULT onNotifyEndAdjust(WPARAM wParam, LPNMHDR pNMHDR, BOOL& bHandled);
LRESULT onSetRedraw(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// manage the subclassing of the IE rebar
void subclass();
void unsubclass();
void handleSettings();
void setButtonMenu2();
bool findButton(HWND hWndToolbar);
private:
// handles to the various things
HWND m_hWnd;
HWND m_hWndToolbar, m_hWndRebar, m_hWndTooltip;
HMENU m_hMenu;
int m_buttonID;
int m_ieVer;
CIEWindow *m_ieWindow;
// toolbar finding functions
void scanForToolbarSlow();
void getRebarHWND();
void setButtonMenu();
};
It doesn't matter what CRebarHandler does, these lines are bad:
CRebarHandler *test=NULL;
test->setButtonMenu2();
You have this pointer and you first say "it doesn't point to anything" and then you say "go ahead and use what the pointer is pointing to, to set the button menu." Not gonna happen.
Try:
CRebarHandler test;
test.setButtonMenu2();
or
CRebarHandler test= new CRebarHandler();
test->setButtonMenu2();
Depending on the lifetime you want for test. You might want to use the constructor-that-takes-parameters instead of the default constructor. My point is that you have to have a CRebarHandler in order to call a method on it.

Resources