MFC List Control Debug Assesrtion Failed - mfc

I am trying to show a dialog box with a list control filled with values from a CString Array from the parent windows but gettng debg assertion failed error on InsertItem command of ListControl.
Csheetnamesdlg is the child dialog box class.
and m_sheetnames is the listcontrol variable.
Csheetnamesdlg tempdlg;
LVITEM lvItem;
for(int j=0;j<tempsheetnames.GetSize();j++)
{
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
tempstring=tempsheetnames.GetAt(j);
lvItem.pszText = const_cast<LPTSTR>((LPCTSTR)tempstring);
tempdlg.m_sheetnames.InsertItem(&lvItem);
}
tempdlg.DoModal();

You can not use a member list control until the dialog is created. The Dialog and all of its children is created after you called DoModal.
So the correct way is to fill the list box in OnInitDialog or DoDataExchange.
Tipp: Always give aus the line and statement were you get the ASSERT
In this case I am sure that a m_hWnd handle is NULL, so this tells you the reason.

Related

How can I determine the index of the top item displayed in the drop-down list of a TComboBox?

How can I find the index of the top item in the drop-down list of a TComboBox?
I know that a TListBox has a TopIndex property, but I can't find anything similar to this for a TComboBox.
I'm using C++Builder in RAD Studio 10.4 Update 2.
Since FMX's TListBox does not have a TopIndex property, I'm going to assume you are referring to VCL instead.
In the VCL, you can access the HWND of the TComboBox's drop-down ListBox by calling the Win32 GetComboBoxInfo() function on (or sending a CB_GETCOMBOBOXINFO message to) the HWND returned by the TComboBox::Handle property. And then you can send an LB_GETTOPINDEX message to the ListBox HWND.
COMBOBOXINFO info = { sizeof(COMBOBOXINFO) };
GetComboBoxInfo(ComboBox1->Handle, &info);
// or: SendMessage(ComboBox1->Handle, CB_GETCOMBOBOXINFO, 0, (LPARAM)&info);
int index = SendMessage(info.hwndList, LB_GETTOPINDEX, 0, 0);

Why did I fail to find window use parent specified in Spy++?

Imagine there is a web page with a <input type="file" />. I open this page in Firefox, and click on the file button. Then a dialog will popup.
I want to set the file name edit of the popup dialog programmatically in C++:
First I use Spy++ to check window class, the Firefox window and popup dialog properties in Spy++ look like:
Firefox window:
Handle: 001E013E
Caption: Table with objects - Mozilla Firefox
Class: MozillaWindowClass
Popup dialog:
Handle: 004508BE
Caption: File Upload
Class: #32770 (Dialog)
Spy++ also shows browser window is the parent of popup dialog.
My code looks like:
#include <Windows.h>
#include <stdio.h>
int main()
{
HWND hBrowser = FindWindow(L"MozillaWindowClass", NULL);
printf("Browser hwnd=%X\n", hBrowser);
HWND hDialog = FindWindowEx(hBrowser, NULL, L"#32770 (Dialog)", NULL);
printf("Dialog hwnd=%X\n", hDialog);
system("pause");
}
But the value of hBrowser does not equal the value in Spy++ dialog, and value of hDialog is NULL. I have only one Firefox window opened, with only one tab.
Then I tried to change my code to:
// 0x001E013E is the handle in Spy++
HWND hDialog = FindWindowEx((HWND)0x001E013E, NULL, L"#32770 (Dialog)", NULL);
hDialog still outputs as NULL.
Questions:
Why the handle in Spy++ and the one I get in program is not the same?
Does the "parent window" in Spy++ have the same meaning with the parent parameter in FindWindowEx?
Note: I can't use window title to do the find, due to localization issue (Firefox may be installed in languages other than English).
MozillaWindowClass is the owner of the open dialog, it is not a parent you can use with FindWindowEx. There can also be more than one MozillaWindowClass window so it is better to look for the dialog first:
BOOL CALLBACK FindMozillaOpenFilenameDialogEnumProc(HWND hWnd, LPARAM param)
{
HWND*pData = (HWND*) param;
if (GetClassLongPtr(hWnd, GCW_ATOM) == 32770) // Found a dialog?
{
HWND hOwner = GetWindow(hWnd, GW_OWNER);
if (hOwner)
{
WCHAR buf[100];
GetClassName(hOwner, buf, 100);
if (0 == lstrcmp(buf, TEXT("MozillaWindowClass"))) // The dialog is owned by a Mozilla window?
{
HWND hCombo = GetDlgItem(hWnd, 0x047c); // cmb13
GetClassName(hCombo, buf, 100);
buf[8] = '\0'; // Some Windows versions use ComboBox and some use ComboBoxEx32, we only care if it is some type of combobox
if (0 == lstrcmp(buf, TEXT("ComboBox"))) // The dialog contains a ComboBox with the expected ID?
{
*pData = hWnd;
return false;
}
}
}
}
return true;
}
int main()
{
HWND hDialog = NULL;
EnumWindows(FindMozillaOpenFilenameDialogEnumProc, (LPARAM) &hDialog);
printf("Dialog hwnd=%X\n", hDialog);
if (hDialog)
{
HWND hCombo = GetDlgItem(hDialog, 0x047c);
SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM) TEXT("c:\\foo\\bar.exe")); // Could also use CDM_SETCONTROLTEXT?
}
return 0;
}
This code relies on undocumented and internal names and window relationships, it could break at any time.
Keep in mind that "MozillaWindowClass" is a internal Mozilla name and could change at any time. The documented cmb13 id of the filename control is only documented for GetOpenFileName and GetSaveFileName but not for IFileDialog based dialogs. You really should use UI Automation when you interact with the open dialog in another application!

Common Dialogboxes Win32

I have a common color dialog box that I want to activate on a menu press.
Unfortunately, every time I press on the item, the window loses focus, as if a dialog box is coming up, but the dialog box never shows up.
The code I'm using right now is below:
case ID_TOOL_CHOOSECOLOR:
//show colour dialog
ChooseColor(&cc);
and I've initialized my CHOOSECOLOR structure like this:
cc.lStructSize = sizeof (CHOOSECOLOR) ;
cc.hwndOwner = NULL ;
cc.hInstance = NULL ;
cc.rgbResult = RGB (0x80, 0x80, 0x80) ;
cc.lpCustColors = crCustColor ;
cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
cc.lCustData = 0 ;
cc.lpfnHook = NULL ;
cc.lpTemplateName = NULL ;
What's weird is, the dialog box only shows up after I press the "ALT" key (and only the alt key). Any tips?
I'm trying to do this in an MDI document by the way.
Thanks
The only problem I can see is that you did not specify an owner for the dialog. This could lead to the dialog showing behind your main window. Specify the handle of your main window to be the dialog's owner.
Read more about window ownership on the Window Features page on MSDN.
Fixed it!
Turns out, the issue I had was in the main window's WndProc.
I had set my WM_PAINT command to return 0; instead of break;.
Changing my return 0 to break solved everything!
I think this is cause my return would exit the wndproc, whereas break would allow me to continue to the return MDIFrameProc(hwnd, message, wparam, lparam) .
I maybe wrong, but that's the best explanation that I can come up with that explains why break works but return 0 doesn't.
After you paint, make sure you call ValidateRect(HWND,CONST RECT*);
// https://learn.microsoft.com/en-us/windows/win32/dlgbox/color-dialog-box
// http://winapi.freetechsecrets.com/win32/WIN32Choosing_a_Color.htm
COLORREF acrCustClr[16]; // array of custom colors
CHOOSECOLOR cc = {sizeof(cc)};
ZeroMemory(&cc, sizeof(CHOOSECOLOR));
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
cc.lpCustColors = (LPDWORD) acrCustClr;
BOOL fOk = ChooseColor(&cc);
if (fOk) {
}

Comparing current foreground window handle

I need to get the current foreground window handle and compare it to a saved previous window handle to see if they match, but I can't use foreground window title, because the title changes often
This is the code I'm using to compare the titles
char cWindow[MAX_PATH];
char nWindow[MAX_PATH];
GetWindowTextA(GetForegroundWindow(), cWindow, sizeof(cWindow));
//Later in code
GetWindowTextA(GetForegroundWindow(), cWindow, sizeof(cWindow));
if (strcmp(nWindow, cWindow) != 0)
{
fputs("found!",file);
strcpy(nWindow, cWindow);
}
When you want to check whether the foreground window has changed, you should compare the window handles directly, without their titles.
HWND oldForegroundWindow = GetForegroundWindow();
HWND newForegroundWindow = GetForegrundWindow();
if (newForegroundWindow != oldForegroundWindow) {
ForegroundWindowHasChanged(oldForegroundWindow, nForegroundWindow);
oldForegroundWindow = newForeroundWindow;
}
Errr you are NOT setting nWindow to anything both your calls are setting cWindow. Do you think that may be an issue?

Loop through MFC Child Dialogs, MDIFrames etc

Is there a way to loop through all MFC Child Dialogs, MDI frames and etc? And is there a way to find out which dialog or window I am looping through?
Taken from Анатолий Тутов (https://web.archive.org/web/20140110220804/http://www.asis.ru/posts/27):
for (CWnd *pWnd = GetWindow(GW_CHILD); pWnd != NULL; pWnd = pWnd->GetNextWindow(GW_HWNDNEXT))
{
//Insert your code here. pWnd is a pointer to control window.
}
You could use EnumChildWindows to iterate through child windows of certain window.