MFC Ribbon Control and AFX_WM_ON_CHANGE_RIBBON_CATEGORY - winapi

A have a window with Ribbon control. Ribbon control has three categories in it... I have handler for AFX_WM_ON_CHANGE_RIBBON_CATEGORY message:
LPARAM CMainFrame::OnRibbonCategoryChanged(WPARAM wp, LPARAM lp)
{
CMFCRibbonCategory *pCategory=m_wndRibbonBar.GetActiveCategory();
int nCategory=m_wndRibbonBar.GetCategoryIndex(pCategory);
return 0;
}
When I start this application on my Windows7 machine my categories have indices: 1, 2, 3, but if i start the same application on Windows Server 2008, then indices will be 0, 1, 2...
Is it a BUG? How to make it work on different platforms?

I Suggest you to use category name instead of its index.
Example:
LPARAM CMainFrame::OnRibbonCategoryChanged(WPARAM wp, LPARAM lp)
{
CMFCRibbonCategory *pCategory=m_wndRibbonBar.GetActiveCategory();
CString strCatName(pCategory->GetName());
if (strCatName.CompareNoCase(_T("Home")) == 0)
{
// Do something
}
else if (strCatName.CompareNoCase(_T("My Category")) == 0)
{
// Do something
}
return 0;
}
Hope it can help.

Related

HideCaret() has no effect on Windows XP (x64)

I'm trying to hide caret on my read-only EDIT control. On Windows 10 (x64) caret is hiding and everything works OK. But on Windows XP (x64) caret is still visible. What I did wrong?
BOOL OnCommand(HWND hWnd, INT ID, HWND hWndCtl, UINT codeNotify) {
switch (ID) {
case IDC_EDIT1:
switch (codeNotify) {
case EN_SETFOCUS:
HideCaret(hWndCtl);
break;
}
break;
}
return FALSE;
}
BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_COMMAND:
return OnCommand(hWnd, (INT)LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
}
return FALSE;
}
Much easier.
Don't give the edit control the focus. You may remove the WS_TABSTOP style.
Don't use an Edit control at all and use a static control. This also has never a Caret.
Why do you use a Edit control and want to hide the caret.
Seams to be an X-Y question.

Hot tracking list item selection in a combo box

I have a combo box and I need to intercept the changement of the selection while the user changes the selection by just hovering with the mouse without clicking. This is for displaying complementary information about the item the user is hovering over.
CBN_SELCHANGE won't do the job, because this message gets fired only when the user has actually changed the selection by clicking on one of the combo box items or when the up/down keys are pressed.
Apparently no message is fired while the user is just hovering over the the combobox.
Illustration
E.g: I need to know when the user moves the mouse from the entry 2 to the entry 33.
This is c++ subclass based on c# article which you mentioned:
LRESULT CALLBACK ComboProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubClass, DWORD_PTR)
{
if (msg == WM_CTLCOLORLISTBOX)
{
COMBOBOXINFO ci = { sizeof(COMBOBOXINFO) };
GetComboBoxInfo(hwnd, &ci);
if (HWND(lParam) == ci.hwndList)
{
int pos = SendMessage(ci.hwndList, LB_GETCURSEL, 0, 0);
OutputDebugStringA(std::to_string(pos).c_str());
OutputDebugStringA("\n");
}
}
if (msg == WM_NCDESTROY)
{
RemoveWindowSubclass(hwnd, ComboProc, uIdSubClass);
}
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
...
SetWindowSubclass(hComboBox, ComboProc, 0, 0);
This was tested on Windows 10.
This can only report the hover selection in drop down list, it can't change the selection.

Select all text in edit contol by clicking Ctrl+A

How to select all text in edit control by pressing Ctrl+A?
I can catch Ctrl+A for parent window in WndProc.
But I don't know how to catch ctrl+a which are applied for edit control.
Also I tried to use accelerators, but again it applies only for parent window.
Thanks.
EDIT: 1-st the simplest method
This method Based on #phord's answers in this question:
win32 select all on edit ctrl (textbox)
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
if (msg.message == WM_KEYDOWN && msg.wParam == 'A' && GetKeyState(VK_CONTROL) < 0)
{
HWND hFocused = GetFocus();
wchar_t className[6];
GetClassName(hFocused, className, 6);
if (hFocused && !wcsicmp(className, L"edit"))
SendMessage(hFocused, EM_SETSEL, 0, -1);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
EDIT: 2-nd method
Need to use CreateAcceleratorTable + TranslateAccelerator functions:
//global variables:
enum {ID_CTRL_A = 1};
HACCEL accel;
//main procedure
ACCEL ctrl_a;
ctrl_a.cmd = ID_CTRL_A; // Hotkey ID
ctrl_a.fVirt = FCONTROL | FVIRTKEY;
ctrl_a.key = 0x41; //'A' key
accel = CreateAcceleratorTable(&ctrl_a, 1); //we have only one hotkey
//How GetMessage loop looks
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
if (!TranslateAccelerator(hWnd, accel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
//in WndProc we must add next cases
case WM_COMMAND:
{
if (LOWORD(wParam) == ID_CTRL_A && HIWORD(wParam) == 1)
{
//on which control there was pressed Ctrl+A
//there is no way of getting HWND through wParam and lParam
//so we get HWND which currently has focus.
HWND hFocused = GetFocus();
wchar_t className[6];
GetClassName(hFocused, className, 6);
if (hFocudsed && !wcsicmp(className, L"edit"))
SendMessage(hFocused, EM_SETSEL, 0, -1);
}
}
break;
case WM_DESTROY:
{
DestroyAcceleratorTable(accel);
PostQuitMessage(0);
}
break;
As you can see this is pretty simple.
No need to handle WM_KEYDOWN! I know that most examples here (and CodeProject and many other places) all say there is, but it does not cure the beep that results whenever a WM_CHAR arises that is not handled.
Instead, try this:
LRESULT CALLBACK Edit_Prc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
if(msg==WM_CHAR&&wParam==1){SendMessage(hwnd,EM_SETSEL,0,-1); return 1;}
else return CallWindowProc((void*)WPA,hwnd,msg,wParam,lParam);
}
Remember to subclass the EDIT control to this Edit_Prc() using WPA=SetWindowLong(...) where WPA is the window procedure address for CallWindowProc(...)
First change the WindowProc for the edit control:
if (!(pEditProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, (LONG)&EditProc)))
{
assert(false);
return false;
}
Then in the new window proc, process the ctrl+a:
LRESULT CALLBACK EditProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
if (msg == WM_KEYDOWN) {
if (GetKeyState(VK_CONTROL) & 0x8000 && wParam == 'A') {
SendMessage(hwnd, EM_SETSEL, 0, -1);
}
}
return CallWindowProc(pEditProc, hwnd, msg, wParam, lParam);
}
Good News!
It seems Edit Controls (not multiline) now support Ctrl + A natively on Win10.
My current Windows SDK version is 10.0.17763.0.
Only tested on simple GUI APPs created with pure Windows API.
MFC APPs should have the same result.
The test binary platform is x86, and OS is Win10 x64.
Noob proof version?
I have written my own version using an accelerator table aswell.
This cleans out the WinMain a bit, and I tried to make everything as n00b proof as possible (since I am one).
Also the enum is ommited, since it is not needed.
As stated I am only a beginner in using the winapi, so please by all means
correct me if I am wrong.
In "Resource.h" I define two ID's
One for the accelerator table we will be using,
and one for the selectall command we will be using.
Inside Resource.h:
#define IDR_ACCEL1 101
#define ID_SELECT_ALL 9003
Then inside of the resource file (in vs2017 this is PROJECTNAME.rc)
we define the accelerator table.
PROJECTNAME.rc:
IDR_ACCEL1 ACCELERATORS
{
0x41, ID_SELECT_ALL, VIRTKEY, CONTROL // ctrl-A
}
Description
0x41 is virtkey 'a'.
ID_SELECT_ALL (will be the ID of the command, this should be the ID we defined in the Resource.h file.
The VIRTKEY keyword indicated that the 0x41 should be interpreted as a virtual key.
CONTROL is the modifier needed to combine the a with (ctrl+a).
Then inside the WinMain function load the accelerator:
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
if (hAccel == NULL)
{
MessageBox(NULL, _T("Failed to load accelerator table!"),_T("Error"), MB_OK | MB_ICONEXCLAMATION);
return 0;
}
Note: after trying to define hAccel we do a check to see if a valid handle has be assigned.
While this is not needed, I believe it's better convention.
After this we add the TranslateAccelerator function to the message loop, so the command can be processed in the window procedure:
BOOL bRet;
while (bRet = GetMessage(&Msg, NULL, 0, 0) > 0)
{
if (bRet == -1)
{
// Error handling can be done here.
}
else if (!TranslateAccelerator(hwnd, hAccel, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
Then finally inside the Window procedure
We add the code as follows:
switch(msg)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case ID_SELECT_ALL:
{
HWND hEdit;
hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT) // Define IDC_MAIN_EDIT with an integer value in "Resource.h".
}
break;
}
break;
}
}
Note: The message passed to WM_COMMAND is the ID we defined for the ctrl+a accel.
I hope this will help fellow n00bies.

Windows API animated window controls

Lets say I have a window with 2 dialogs, each having its own set of controls/information.
One is displayed on the window and the other is hidden, and I have a button switching between them.
How would I animate the transition between the 2 dialogs, like having it slide back and forth?
Note: I'm trying to use only the windows api for this.
Hans is correct, you can use the Windows API AnimateWindow.
AnimateWindow Function
here an example:
int CALLBACK EventDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
AnimateWindow(hwndDlg, 100, AW_SLIDE | AW_HOR_POSITIVE);
return 1;
}
case WM_PAINT:
{
return 1;
}
}
return 0;
}

Not able to get the coordinates of a particular window (I've tried the examples...still ) in V C++

I have been trying various code snippets here and there, but still not successful.I am simply trying to find one of the open windows (it is the Browser window) using FindWindow(NULL,WINDOWTITLE), with a specific Title string. Once I get the handle of the window, I need the coordinates using GetWindowRect.
This code gets me the coordinates, but seems like it's in an infinite loop, there are about a 100 lines of output with the coordindates, should be just 1. I don't see any while construct (originally a Java programmer)... wonder why it's repeating...
struct WindowInfo
{
HWND m_hWnd;
string m_title;
WindowInfo(HWND hwnd, string title) : m_hWnd(hwnd), m_title(title) {}
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
vector<WindowInfo*> & windows = *(vector<WindowInfo*>*)lParam;
char title[256];
HANDLE wndHandle;
LPCWSTR WINDOWTITLE = L"eBargain 2 Share - Windpos Internet Explorer";
RECT rRect;
LPRECT lpRect;
RECT rc;
hwnd = FindWindow(NULL,WINDOWTITLE);
GetWindowRect(hwnd,&rc);
printf("Position: %d x %d\tSize: %d x %d\n",rc.left,rc.top,rc.right- rc.left,rc.bottom-rc.top);
/* Enumerating through all the windows tells me that I am on the right track... (Should I just try to find the TITLE STRING by comparing every title from the following enumeration ?
*/
GetWindowTextA(hwnd, title, 256);
windows.push_back(new WindowInfo(hwnd,title));
// printf("%s\n", title);
return TRUE;
}
int main()
{
vector<WindowInfo*> windows;
BOOL ret = EnumWindows(EnumWindowsProc, (LPARAM) &windows);
if ( ret )
{
//windows have windowinfo of all enumerated windows
}
}
Your EnumWindowsProc seems to be a bit confused - are you enumerating or using FindWindow?
If you enumerate, simply get the window title and compare to the string you search for:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
char title[256];
if (GetWindowTextA(hwnd, title, 256)) {
if (strcmp(title, "eBargain 2 Share - Windpos Internet Explorer") == 0) {
/* GetWindowRect ... */
}
}
return TRUE;
}
Or, if you're using FindWindow, no need to enumerate:
int main() {
HWND hwnd = FindWindowA(0, "eBargain 2 Share - Windpos Internet Explorer");
if (hwnd) {
/* GetWindowRect ... */
}
}

Resources