MFC, Threads and Responsive GUI
-
Hello everybody, This will take a little while to describe the problem I'm facing, and I will appreciate your patience. I'm creating a pretty large SDI MFC application, with a lot of options and controls. Most of the application screens are list based. If that matters, imagine MS Word 2007 with editable list instead editable document. Some of the controls activate a pretty lengthy operations that do work on the list, and update its entries. These operations use worker threads to do their work. Now, the problem. I want to update the list on the go while disabling all the controls, except one - the "cancel" button. A simple EnableWindow(FALSE) wouldn't work, as the application is Ribbon based. I.e. to make the buttons look disabled I must handle ON_UPDATE_COMMAND_UI. Simple message pump wouldn't work as well, because of MFC message routing. Can anybody suggest a proper approach for such an application? That is both relative simple and general (I have many different operations that activate worker threads).
-
Hello everybody, This will take a little while to describe the problem I'm facing, and I will appreciate your patience. I'm creating a pretty large SDI MFC application, with a lot of options and controls. Most of the application screens are list based. If that matters, imagine MS Word 2007 with editable list instead editable document. Some of the controls activate a pretty lengthy operations that do work on the list, and update its entries. These operations use worker threads to do their work. Now, the problem. I want to update the list on the go while disabling all the controls, except one - the "cancel" button. A simple EnableWindow(FALSE) wouldn't work, as the application is Ribbon based. I.e. to make the buttons look disabled I must handle ON_UPDATE_COMMAND_UI. Simple message pump wouldn't work as well, because of MFC message routing. Can anybody suggest a proper approach for such an application? That is both relative simple and general (I have many different operations that activate worker threads).
I do not understand this statement: >> Simple message pump wouldn't work as well, because of MFC message routing. Are you referring to a local message loop? Of course EnableWindow won’t work, since ribbon Windows controls, all controls with are derived from CObject and are represented by just image drawn by the ribbon control. Few of them are actually hosting Windows control (like CMFCRibbonEdit for example). Anyway, if you update some data in the background using worker thread, use a variable that would tell update command handler to toggle enabled state: disable when thread is still running, and enable when thread is done, using CCMdUI. You can also consider using ON_UPDATE_COMMAND_UI_RANGE, for the range of the ribbon’s panel controls.
JohnCz
-
I do not understand this statement: >> Simple message pump wouldn't work as well, because of MFC message routing. Are you referring to a local message loop? Of course EnableWindow won’t work, since ribbon Windows controls, all controls with are derived from CObject and are represented by just image drawn by the ribbon control. Few of them are actually hosting Windows control (like CMFCRibbonEdit for example). Anyway, if you update some data in the background using worker thread, use a variable that would tell update command handler to toggle enabled state: disable when thread is still running, and enable when thread is done, using CCMdUI. You can also consider using ON_UPDATE_COMMAND_UI_RANGE, for the range of the ribbon’s panel controls.
JohnCz
You can post a message from your thread to the view that contains your list. Your view can then add the data to the list (or modify it as needed) and then call UpdateWindow() fot the list. UpdateWindow bypasses the normal winproc and is handled immediately by the window. Hope this helps.
Karl - WK5M PP-ASEL-IA (N43CS) PGP Key: 0xDB02E193 PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
-
You can post a message from your thread to the view that contains your list. Your view can then add the data to the list (or modify it as needed) and then call UpdateWindow() fot the list. UpdateWindow bypasses the normal winproc and is handled immediately by the window. Hope this helps.
Karl - WK5M PP-ASEL-IA (N43CS) PGP Key: 0xDB02E193 PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
I do not think that UpdateWindow addresses the original problem. UpdateWindow triggers system to sends (not posts) WM_PAINT message, therefore message is not placed in the queue. SendMessage causes system to call windows procedure directly, therefore this s a blocking call. Anyway, original problem is to update UI controls on the ribbon, not list control. Setting variable using proper synchronization is I think less expensive than posting the custom message from the worker thread; however I think the difference is negligible. If PostMessage is used, the handler can set variable to be used in Update UI handlers.
JohnCz
-
Hello everybody, This will take a little while to describe the problem I'm facing, and I will appreciate your patience. I'm creating a pretty large SDI MFC application, with a lot of options and controls. Most of the application screens are list based. If that matters, imagine MS Word 2007 with editable list instead editable document. Some of the controls activate a pretty lengthy operations that do work on the list, and update its entries. These operations use worker threads to do their work. Now, the problem. I want to update the list on the go while disabling all the controls, except one - the "cancel" button. A simple EnableWindow(FALSE) wouldn't work, as the application is Ribbon based. I.e. to make the buttons look disabled I must handle ON_UPDATE_COMMAND_UI. Simple message pump wouldn't work as well, because of MFC message routing. Can anybody suggest a proper approach for such an application? That is both relative simple and general (I have many different operations that activate worker threads).
Here's an excellent article on worker threads: WorkerThreads[^]
"Real men drive manual transmission" - Rajesh.
-
Hello everybody, This will take a little while to describe the problem I'm facing, and I will appreciate your patience. I'm creating a pretty large SDI MFC application, with a lot of options and controls. Most of the application screens are list based. If that matters, imagine MS Word 2007 with editable list instead editable document. Some of the controls activate a pretty lengthy operations that do work on the list, and update its entries. These operations use worker threads to do their work. Now, the problem. I want to update the list on the go while disabling all the controls, except one - the "cancel" button. A simple EnableWindow(FALSE) wouldn't work, as the application is Ribbon based. I.e. to make the buttons look disabled I must handle ON_UPDATE_COMMAND_UI. Simple message pump wouldn't work as well, because of MFC message routing. Can anybody suggest a proper approach for such an application? That is both relative simple and general (I have many different operations that activate worker threads).