I have this CTaskDialog that I am working on:
The code is as follows:
CTaskDialog dlg(_T("How would you like to download the data?"),
_T("Download Schedule Information"),
_T("Meeting Schedule Assistant"), TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON);
dlg.SetMainIcon(TD_INFORMATION_ICON);
dlg.SetFooterIcon(TD_INFORMATION_ICON);
dlg.SetFooterText(_T("All assignments for the selected weeks will be reset."));
dlg.AddRadioButton(44444, _T("Download data for all weeks"));
dlg.AddRadioButton(44445, _T("Download data for selected week"));
dlg.AddRadioButton(44446, _T("Download data for selected week and all additional weeks"));
// Set Width in dialog units (40% screen width)
int iPixelWidth = (::GetSystemMetrics(SM_CXSCREEN) / 100) * 40;
int iDialogUnitsWidth = MulDiv(iPixelWidth, 4, LOWORD(GetDialogBaseUnits()));
dlg.SetDialogWidth(iDialogUnitsWidth);
if(dlg.DoModal() == IDOK)
{
auto iSelection = dlg.GetSelectedRadioButtonID();
}
Is it possible to set the main icon as a question? I can only see these defines in the source:
#define TD_WARNING_ICON MAKEINTRESOURCEW(-1)
#define TD_ERROR_ICON MAKEINTRESOURCEW(-2)
#define TD_INFORMATION_ICON MAKEINTRESOURCEW(-3)
#define TD_SHIELD_ICON MAKEINTRESOURCEW(-4)
The SetMainIcon member function is what you're looking for. Like most functions that deal with Win32 resources, it has two overloads:
void SetMainIcon(
HICON hMainIcon
);
void SetMainIcon(
LPCWSTR lpszMainIcon
);
The first takes a handle to an icon resource (HICON), while the second takes a string identifying a resource from which an icon resource can be loaded.
If you want to set the task dialog to display your application's icon, then you can simply pass in the appropriate HICON. You can also use a custom icon loaded from your application's resources.
I'm not entirely sure, but I think what you're asking is how to use a question-mark icon. Note first that the use of such icons in message boxes has been deprecated since Windows 95, and Microsoft strongly discourages their use. It is recommended that you only use them to denote entry points to online help. Quoting from the Standard Icons section of the official Win32 style guide:
Question mark icons
Use the question mark icon only for Help entry points. For more information, see the Help entry point guidelines.
Don't use the question mark icon to ask questions. Again, use the question mark icon only for Help entry points. There is no need to ask questions using the question mark icon anyway it's sufficient to present a main instruction as a question.
Don't routinely replace question mark icons with warning icons. Replace a question mark icon with a warning icon only if the question has significant consequences. Otherwise, use no icon.
So, this is why there's no standard question mark icon defined. These TD_*_ICON defines are straight from the Win32 headers for the Task Dialog (they're the same ones you'd use with the TASKDIALOGCONFIG structure), not part of the MFC wrapper class.
If you absolutely must use this icon, the workaround is as follows:
const HICON hiconQuestion = AfxGetApp()->LoadStandardIcon(IDI_QUESTION);
dlg.SetMainIcon(hiconQuestion);
(Note that the same HICON could be passed to the CTaskDialog's SetFooterIcon member function.)
Related
I am trying to set up a MFC C++ App in Visual Studio 2019 such that modifies the user's text as they are typing.
Current layout is 2 radio buttons,
ID= rdbOn (set to Group = True, with Value int variable m_isOn = 1)
ID= rdbOff, m_isOn value would be = 0
and 1 Edit Control,
ID= txtInputBox, with Value CString variable m_inputString
Currently, for testing I can see how it would work for a button on click, it would take something like the following and just SetDlgItemText of the result. But that would be after they have typed, not WHILE they are typing.
void Onsomebtnclick()
{
//convert CString to String of m_inputString
//do some string manipulation
//convert back to CString
//SetDlgItemText(txtInputBox, result)
}
Update:
got EN_CHANGE to work
I was able to get EN_CHANGE working with the flag suggestion from user #GoGoWorx. However, now I just have a slight problem that the cursor is back to the beginning of the edit control txtInput.
I'm reading about using a CEdit::SetSel but don't know how to use that directly in my code. I tried
CEdit control MFC, placing cursor to end of string after SetWindowText
someDlg::someFunction()
{
//some logic stuff to get a result string
SetDlgItemText(txtInputBox, result);
//need it to set the cursor to the end
//I tried these, but it didn't recognize (expression must have class type?)
//txtInputBox.SetSel(0, -1);
//txtInputBox.SetSel(-1);
}
It sounds like you need to use the ON_EN_CHANGE message-map notification (called after the control has been updated due to typing or pasting for example)
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_EN_CHANGE(IDC_EDIT_CONTROL, &CMyDialog::OnEnChangeEditControl)
END_MESSAGE_MAP()
void CMyDialog::OnEnChangeEditControl()
{
// Copy or call your Onsomebtnclick() here
}
I'm not sure what you're using for the numeric identifier for the edit control, since these are typically upper case defines - replace IDC_EDIT_CONTROL above with your define (possibly txtInputBox, but again, these are normally upper case, so I'm not sure).
Also change CMyDialog for the name of your dialog class too.
Note that we're using the ON_EN_CHANGE message-map handler here instead of the ON_EN_UPDATE, since the ON_EN_CHANGE message is sent after the control has been updated, whereas ON_EN_UPDATE is called just before it's updated.
The message-map handlers are described in the Remarks section of the CEdit control documentation: https://learn.microsoft.com/en-us/cpp/mfc/reference/cedit-class?view=msvc-160
Regarding your concern about modifying things as the user types - this should be fine, since every change (keystroke or paste from clipboard, etc.) should trigger this handler to be called, where you can change whatever you need. Just be sure that when you're updating the control, you don't trigger the ON_EN_CHANGE again and end up in a recursive 'change' loop.
You might be able to do this with some sort of flag to indicate you're the one updating the control, as opposed to the user, however it's probably better to subclass the CEdit control to do what you're wanting. There are a few examples out there of how to do this (it's not as difficult as it might sound), for example:
https://www.codeproject.com/Articles/27376/Avoiding-EN-CHANGE-notifications
I've been trying to add an icon to an app indicator menu with no success, and I've been using GtkMenu.
I found some code that referenced GMenu and used g_menu_set_icon to display an icon next to the menu label.
What is the difference between these two sets of menu's? Should one be used in favor of the other? GMenu appears to be more full featured, but if I'm supposed to use GtkMenu how would I display an icon?
I have tried this which didn't work. It showed the label text but not the icon.
GtkWidget* NewMenuItemWithIcon(const char* name)
{
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
GtkWidget *icon = gtk_image_new_from_icon_name("status", GTK_ICON_SIZE_MENU);
GtkWidget *label = gtk_label_new(name);
GtkWidget *menu_item = gtk_menu_item_new();
gtk_container_add(GTK_CONTAINER(box), icon);
gtk_container_add(GTK_CONTAINER(box), label);
gtk_container_add(GTK_CONTAINER(menu_item), box);
return menu_item;
}
Update:
It would seem that GMenu doesn't inherit from GtkWidget. So it's a different kind of menu. However, app_indicator_set_menu expects a GtkMenu not a GMenu so the correct menu to use is GtkMenu.
However, the issue of icons remains. I was able to get it working with the deprecated api gtk_image_menu_item
But it's deprecated. So ideally I shouldn't use it. The code above comes directly from api docs. Claiming to be equivalent, it doesn't seem to work.
I understand that for GetTextExtendPoint32 to work correctly, it needs to know the correct font. However, I'm confused as to why SelectObject needs to be called. Example I wanted to calc the length of the text for a check box.
Works:
Size sizeChkBox;
CString csChkBox;
m_ChxBox.GetWindowText(csChkBox);
CDC* dc = m_ChkBox.GetDC();
HFONT hfontChK = (HFONT)GetWindowFont(m_ChkBox.GetSafeHwnd());
SelectObject(*dc, hfontChK);
GetTextExtentPoint32(*dc, csChkBox, strlen(csChkBox), &sizeChkBox);
Doesn't Work:
Size sizeChkBox;
CString csChkBox;
m_ChxBox.GetWindowText(csChkBox);
CDC* dc = m_ChkBox.GetDC();
GetTextExtentPoint32(*dc, csChkBox, strlen(csChkBox), &sizeChkBox);
I guess my question really is why doesn't dc have the correct font already since its "made from the checkbox"?
GetDC(HWND) creates an HDC with all default settings, set up for drawing on a given window. It doesn't actually interrogate the window for its properties: in particular, it doesn't send WM_GETFONT to it.
Realize that WM_SETFONT and WM_GETFONT work only by convention. Nothing says that a window must handle these messages, or use the font provided in its WM_PAINT implementation. Standard controls tend to do this, as a common courtesy, but this is by no means a universal requirement.
I have an edit control which should only take integers betweeen 1 and 99.To achieve this, i used, modifystyle() and limittext().Is there a way to restrict 0 from being entered?
You do not have to control values limit it using your code.
It is easier if you subclass (add variable) edit control using wizard, you can choose UINT type and set minimum and maximum value here.
Also do nto forget to set style to ES_NUMBER (setting Number to True in edit control Properties).
If you absolutely need that, you must derive a class from CEdit and process the input accordingly. Rendering the baloon that says "Unacceptable Character" may be bit tricky to give online-error. The class would be useful only if you are planning to use such class (edit-control) at multiple places, preferably with different ranges.
This is completely different problem from than one in your original post.
Make sure that your spin control follows immediately edit control in the Z-order (tab order).
In the resource set spinner style to: UDS_AUTOBUDDY UDS_SETBUDDYINT, UDS_ALIGNRIGHT,.
This will causse spinner to: choose edit control as buddy, set integer in edit box, place itself inside edit control to the right edge.
To do that, in the properties for the spinner set: "Auto Buddy" True, "Set Buddy Integer" True and "Alingment" to Right Align.
You do nto have to set minimum and maximum for the edit control, handle it now in the command handler for EN_CHANGE notification.
Place this code in the handler.
void CYourDlg::OnEnChangeEditNum()
{
int iValue = GetDlgItemInt(IDC_EDIT1);
if(iValue < 1 || iValue > 99)
{
m_Edit.ShowBalloonTip(_T("Number Out of Range"), _T("Value must fall between 1 and 99."), TTI_INFO_LARGE);
}
}
How to change font in all dialog forms in a visual c++ application?
I want to set Tahoma style.
Thanks.
You can set the font for a dialog in the resource it's created from. I believe that'll change the font on all the standard controls as well. If you have custom controls, you'll have to do additional work.
Note that if you want to have the font match the default UI font for the computer, then you can use a virtual font like "MS Shell Dlg 2" which will be mapped to Tahoma on XP, and Segoe UI on Vista+.
Replacing font in each dialog of your application would be rather tedious job.
You can employ MFC to do it for you.
Check InitInstance of your app. Look at AfxEnableControlContainer();
It is being called woithout any parameter even though AfxEnableControlContainer is declared as
void AFX_CDECL AfxEnableControlContainer(COccManager* pOccManager=NULL);
COccManager is a very interesting class and is used when has occ ( OLE custom controls) support, managing OLE container and site classes. All MFC applications are created by default with occ support. If you do not see AfxEnableControlContainer in the code generated by wizard, you do not have occ support enabled.
Anyway, instead using default occ implementation, use own and change it to change the font.
Derive class from COccManager. In this sample I call it CDlgOccManager. Override virtual PreCreateDialog:
virtual const DLGTEMPLATE* PreCreateDialog(_AFX_OCC_DIALOG_INFO* pOccDialogInfo,
const DLGTEMPLATE* pOrigTemplate);
In the implementation:
const DLGTEMPLATE* CDlgOccManager::PreCreateDialog(_AFX_OCC_DIALOG_INFO* pOccDialogInfo, const DLGTEMPLATE* pOrigTemplate)
{
CDialogTemplate RevisedTemplate(pOrigTemplate);
// here replace font for the template
RevisedTemplate.SetFont(_T("Tahoma"), -16);
return COccManager::PreCreateDialog (pOccDialogInfo, (DLGTEMPLATE*)RevisedTemplate.Detach());
}
Now you are changin font for all dialogs. Remember changing AfxEnableControlContainer call:
PROCESS_LOCAL(CDlgOccManager, pManager);
BOOL CDlgFontChangeApp::InitInstance()
{
AfxEnableControlContainer(pManager.GetData());
.
.
.
}
DO not forget to
#include "DlgOccManager.h"
For new verion of the MFC include afxdisp.h for older, occimpl.h for COccManager.
I just noticed something. It is not a blunder but it needs an explanation.
I have kept this code in my repository for a very, very, very long time.
It was a time when DLLs kept all data as global, making data available to all modules that loaded this dll. In order to force data to be stored in TLS area, I used PROCESS_LOCAL macro that expands to invoking CProcessLocal class that is still alive.
You can remove this macro and replace it with:
BOOL CDlgFontChangeApp::InitInstance()
{
CDlgOccManager* pManager = new CDlgOccManager();
AfxEnableControlContainer(pManager);
.
.
.
}