I am developing MFC Dialog based application in Visual Studio 2008. I want to use timer that start on start of the application and continue to run and calls a function that performs my task? How can I do this?
Thanks
Just use SetTimer method, and pass two arguments: Timer ID (any number), and the timeout in milliseconds. Then write up OnTimer implementation, and an entry ON_WM_TIMER inside BEGIN_MESSAGE_MAP...END_MESSAGE_MAP.
CWnd::SetTimer takes 3 parameters, but only 2 are required. Pass third argument as NULL.
CWnd::OnTimer
_AFXWIN_INLINE UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD))
You may want to do something like
UINT_PTR myTimer = SetTimer (1, 1000, null); // one event every 1000 ms = 1 s
and react to the ON_TIMER event in your window's event handler:
void CMyView::OnTimer (UINT_PTR nIdEvent)
{
if (nIdEvent == 1)
// handle timer event
}
Alternatively you can pass a pointer to a function handling the timer events. Keeping the handle to the timer allows you to turn it off using KillTimer() in case you have to.
If you want to get the basic idea of using Timers, kindly have a look at this link and go through the step by step procedure on working with timers. After this, you should be able to use timers easily in your application whenever you want.
Link: http://www.functionx.com/visualc/controls/timer.htm
Hope this helps.
Cheers.
Related
I have been tasked with trying to monitor activity in all GUI programs spawned from an initial program and killing them when they become inactive for a set period of time. This cannot be system activity as we must close the programs even if the user is just using another program for a while (not spawned by the initial program). The application spawning processes is a .Net program and that will not change. I was able to use SetWindowsHookEx to set low level hooks (WH_KEYBOARD_LL and WH_MOUSE_LL) from .Net but was unsure of how to associate the messages with the processes I've started (Using System.Diagnostics.Process.) I could hook events from the application doing the hooking, but it would always fail when I tried to hook to a specific thread for a spawned program.
The closest I was able to come was by creating a C++ dll that calls SetWindowsHookEx on behalf of the .Net program. Using this method I am able to hook into the first thread of a spawned notepad.exe, but the callback function is never called. If I specify a thread id of 0 the callback is called when there is activity in the original application so I know the SetWindowsHookEx works in that case.
I don't fully understand hooking yet, but from what I have read this will not work because the dll callback function address will be meaningless to the hooked process. Is that the issue I am running into? If so, is there a way around this or can somebody please suggest an alternative to determining if a spawned process is actively being used?
.Net (C#) code:
private const int WH_MOUSE = 14;
[DllImport("TestHook.dll", EntryPoint="InitializeHook", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern bool InitializeHook(uint hookType, int threadID);
private void HookEm() {
//...
System.Diagnostics.Process testProcess = System.Diagnostics.Process.Start("notepad");
if(!InitializeHook(WH_MOUSE, testProcess.Threads[0].Id)) // The notepad.exe thread I know hooks
MessageBox.Show("Boom!");
//...
}
C++ dll:
HHOOK hookValue;
bool InitializeHook(UINT hookID, int threadID) {
//... Determining which callback to use
hookValue = SetWindowsHookEx(hookID, (HOOKPROC)MouseHookCallback, _dllInstance, threadID);
//...
return hookValue != NULL
}
static LRESULT CALLBACK MouseHookCallback(int code, WPARAM wparam, LPARAM lparam) {
//From what I can see, this is never touched when hooking a thread on an outside process
}
All of this is currently being done on a 32 bit Windows XP computer. I do understand that a separate 64 bit dll would be needed to work with 64 bit applications spawned.
For anyone who encounters a similar issue, our final solution was to check the foreground window on an interval using GetWindowThreadProcessId(GetForegroundWindow(), ref foregroundWindowProcessId) and keeping a map of our spawned process ids. Each time this timer fires we set a boolean value to check in the function that calls CallNextHookEx since it has to be efficient/fast or windows will unhook us. We then use the boolean value above and the system hooks from SetWindowsHookEx to determine if the user is active in our application. No C++ dll was needed for this solution.
I want to create a thread after the creation of a dialog box in MFC. Is there any function that Windows has provided and is automatically called after OnInitDialog so that I can create my thread inside it?
You can simply create your thread in the OnInitDialog function. There's no reason to overcomplicate things by going and searching for a different function, or splitting your initialization code up in two pieces. (There also isn't any such function, because there's no corresponding Windows message that is sent.)
If you want to get your dialog box on the screen before you create the thread, you can just show it manually using the ShowWindow function. For example:
ShowWindow(SW_SHOW);
RedrawWindow();
Also see this post by Raymond Chen: Waiting until the dialog box is displayed before doing something
OnInitDialog() is the main function called upon initialization (in reaction to WM_CREATE).
Why can't you create your thread in there?
I have changed the thread priority to below normal and when the thread executes for the first time I set the thread to normal priory. This works fine. Thanks for your response.
After many years of feeling unsatisifed with the OnTimer solution to draw first view graphics in an MFC dialog app (a favorite playground), this seemed like a nice simple solution:-
Add a WM_HSCROLL handler with class wizard.
At the end of OnInitDialog post a hscroll message with a NULL LPARAM
In handler detect the NULL, draw graphics.
a timer meant that the app was alive for some time before graphics happened, and apparently hscroll is prioritized to happen just after the WM_PAINT message which would erase a picture element to its blank state, deleting anything that was drawn during initdialog.
BOOL CSpecDlg::OnInitDialog()
{
...
PostMessage(WM_HSCROLL,0, (LPARAM)NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
void CSpecDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (pScrollBar==NULL)
{
plot();
}
CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}
How to create timer in WinApi (C++)?
Call the SetTimer function. This allows you to specify a callback function, or to have Windows post you a WM_TIMER message.
You cannot not know this if you write GUI code. Which makes it likely you want to use CreateTimerQueueTimer().
SetTimer. A window handle is needed, and the timer will not be delivered if you aren't pumping messages.
A Good Example for CreateTimerQueueTimer : Here
Another is HERE
call the setTimer() Function. Suppose I called
SetTimer(hWnd,POST_CBIT_TIMER,500,NULL);
Call back function is
UINT nIdEvent ;//global member variable
case WM_TIMER:
if(nIDEvent == POST_CBIT_TIMER)
{
KillTimer(hParent,POST_CBIT_TIMER);
}
break;
I'm writing some code that id like to be able to work with any window, such as a window created through the windows API, MFC, wxWidgets, etc.
The problem is that for some things I need to use the same thread that created the window, which in many cases is just sat in a message loop.
My first thought was to post a callback message to the window, which would then call a function in my code when it recieves the message using one of the params and a function pointer of some sorts. However there doesnt seem to be a standard windows message to do this, and I cant create my own message since I dont control the windows code, so cant add the needed code to the message handler to implement the callback...
Is there some other way to get the thread that created the window to enter my function?
EDIT:
John Z sugessted that I hooked the windows messages. If I do that is there some way to get "ids" for custom messages without the risk of conflicting with any custom messages the window already has?
eg I might do
WM_CALLBACK = WM_APP+1
But if the window I'm hooking has already done something with WM_APP+1 I'm gonna run into problems.
EDIT2:
just found RegisterWindowMessage :)
If you are in the same process as the window you can hook its messages by subclassing it. Check out http://msdn.microsoft.com/en-us/library/ms633570(VS.85).aspx
The key API is SetWindowLong.
// Subclass the edit control.
wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)EditSubclassProc);
// Remove the subclass from the edit control.
SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)wpOrigEditProc);
Alternatively to subclassing, you can use SetTimer to call a function in the window thread.
VOID CALLBACK Function(
HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
// stuff
}
SetTimer(hWnd, event, 0, Function);
Can someone please point me to the easiest way to have a timer in a Win32 service?
I suppose I could create a dummy window for this purpose or have a second thread do tick counts, but what's best? Is there a more elegant way?
Thanks in advance.
You can use Timer Queues (http://msdn.microsoft.com/en-us/library/ms686796.aspx). They don't require an HWND.
Instead of using UI timers (even though you can use the NULL window handle as shown by Mr. 1800-INFO) you can use kernel waitable timer objects. See CreateWaitableTimer in the API docs. These can then be waited-on using WaitForSingleObject or WaitForMultipleObjects, etc, which is especially useful if that's already how your service waits for external events.
If it's not clear from that first link, the SetWaitableTimer function can associate a completion routine (user callback) with the timer. Remember to use the ...Ex versions of WaitForMultipleObjects (etc.) so that the thread is in an "alertable" state.
You can send your main thread WM_TIMER messages. The lParam for the message is the address of a callback function, or you can leave it NULL and handle it yourself in your message pump.
In this example, we are sending the timer to the thread message pump, there is no requirement to have a window associated with the timer.
UINT timer;
VOID CALLBACK Timer(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
KillTimer(0, timer);
}
timer=SetTimer(0, // window handle
0, // id of the timer message, leave 0 in this case
10000, // millis
Timer // callback
);
// pump messages
while (GetMessage) etc...
The Timer callback will be called by DispatchMessage. This question reminded me of the recent ONT.
You can use SetTimer to set the timer, then catch the WM_TIMER message in your message loop.
Example:
// Set a timer to expire in 10 seconds
SetTimer(hwnd,IDT_TIMER1, 10000,(TIMERPROC) NULL);
... then in message loop:
switch (wParam)
{
case IDT_TIMER1:
// Boom goes the dynamite
You can also decleare a function of type TIMERPROC and have that be called when the timer expires, if you don't want to do the message loop handling.
In one of your comments you said that "...the service is processing stuff in other threads, I just need to check the status of a few files every second."
Polling is not an optimal way of checking file status, and will adversely affect system performance. While there are (sometimes) problems doing this over networks, you should check out http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspx or http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx for how to do it and http://blogs.msdn.com/oldnewthing/archive/2006/01/24/516808.aspx for why you should.
Are you just trying to "wake up" every now and then to do some work? You can always use Sleep().
Additionally, I typically have a thread that is in a while(1 == 1) loop with a sleep inside. There I can check for the shutdown request and other misc housekeeping. You could use that system to tickle an event or mutex for the worker thread in the app.