CPRintDialog does not allow print range selection - mfc

Im trying to add printing functionality to my app. I display the CPrintDialog to get the printer options. How do I get the printing range option enabled ? Currently this option is disabled when I doModal() the dialog.

What arguments are you passing to the CPrintDialog constructor? The constructor is declared as
CPrintDialog(BOOL bPrintSetupOnly,
DWORD dwFlags = PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOPAGENUMS|
PD_HIDEPRINTTOFILE|PD_NOSELECTION,
CWnd* pParentWnd = NULL);
so if you don't supply a value for the "dwFlags" argument, you'll get those default flags. The default flags includes PD_NOPAGENUMS, so the page selection controls will be disabled. You've also got to set the maximum page number, too, for the page selection controls to work. Try changing your code to something like
CPrintDialog dlg(FALSE,
PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_HIDEPRINTTOFILE|PD_NOSELECTION);
dlg.m_pd.nMaxPage = 100;
dlg.DoModal();

Does your printing code set the amount of pages that are going to be printed? I don't have any code at hand but I think it's in OnPreparePrintDC() or something like that, where you set m_MaxPage or so member of the object you get as an argument.

Related

How to get the currently selected text in a CComboBoxEx?

My first approach to the problem was to call the GetWindowsText method on the CComboBoxEx control, but I found that there is no associated text. After analyzing the control with Spy++ and reading some documentation on CComboBoxEx, I realised that these type of controls are only the parent of a classic ComboBox:
I tried using the GetLBText() method on the child ComboBox, passing GetCurSel() as an argument, but I only get some wrong text (the correct text should be "English"):
Am I missing something? Thanks in advance!
What you want to do is map the control to a int variable using Class Wizard:
Now it is easy to access the selected text at any time. You need to use the GetItem function. For example (code not tested):
COMBOBOXEXITEM cmbItem;
CString strText;
cmbItem.mask = CBEIF_TEXT;
cmbItem.iItem = m_cbItemIndex;
cmbItem.pszText = strText.GetBuffer(_MAX_PATH);
m_cbMyCombo.GetItem(&cmbItem);
strText.ReleaseBuffer();
In short, you need to use the COMBOBOXEXITEM and initialise it with the right flags to state what information you want to get from the extended combo. That, and the item index. Job done!
I realise that you have your own inherited class, but the mechanics are the same. You don't use GetLBText. You use the structure with the index and GetItem to get the selected text.
In the end I managed to retrieve the correct name; as you can see in the image below, the ComboBox is only a child of a CombBoxEx32:
I retrieved the pointer to the parent ComboBoxEx32 from the child ComboBox, and searched for the text this way:
CString szText;
CComboBoxEx cbParentCombo ;
cbParentCombo.Attach( GetParent()->GetSafeHwnd()) ;
cbParentCombo.GetLBText( GetCurSel(), szText) ;
cbParentCombo.Detach() ;
My mistake was that I was calling GetLBText() directly from the child ComboBox, instead of the parent CComboBoxEx; because of that, all I was getting was some random gibberish. GetLBText() was indeed the correct solution.

How to get the text value of a control through its parent window

I have the following wxDialog parent window:
I have created that parent window by the following code:
settingsFrm settingsWindow(this, "Settings");
settingsWindow.ShowModal();
I have tried to use FindWindowByName to get the value of the first text ctrl as follow:
wxLogMessage(dynamic_cast<wxTextCtrl*>(settingsWindow->FindWindowByName("keywords_txt"))->GetValue());
But unfortunately, it doesn't work and gives me a runtime error.
I don't know if that method suitable to do what I want.
How to get the value/other of a control through its parent window?
From your comments, it seems like you expect the function to find the control from the name of the variable in your code which is not how it works and would be pretty much impossible.
FindWindowByName() uses the window name (and, as a fallback, label, but this is irrelevant here because text controls don't have labels anyhow), so for it to work you need to set the window name when creating the control, using the corresponding parameter of its ctor. This is very rarely useful in C++ code, however, as it's simpler to just store a pointer to the control in some variable and use this instead.
FindWindowByName() can often be useful when creating controls from XRC, however. If you do this, then you should specify names for your controls in XRC and pass the same name to this function.
How did you create the TextCtrl instance? You should have something like wxTextCtrl m_textCtrl1 = new wxTextCtrl(/// arguments); Accessing the value should be very easy, as wxString text = m_textCtrl1->GetValue(); You definitely don't need FindWindowByName just for what you are trying to do here.

What Uxtheme function I must use to get the default size of the minimize, Maximize and close buttons?

I'm using the DrawThemeBackground function to draw some system elements on a canvas, And I need draw the title buttons of a form, the only part that i missed is how i can get the default sizes of the title buttons. Exist any Uxtheme function to get that info?
Looks like this is more difficult then it sounds.
First there's GetThemeMetric or GetThemeInt. But you'll see a lot of references that these functions return a 0x8007490, some "element not found", when you try to retrieve properties of caption buttons.
Then there's GetThemePartSize. This one seems to work some. That is it works ok for instance for WP_CLOSEBUTTON, but it returns nonsense for instance for WP_MINBUTTON. I would not suggest this function's use anyway since it retrieves the default dimensions of the button. If the user has changed the title size for instance, you won't get correct values. Anyway, it could be called like this:
uses
uxtheme, themes;
...
var
Err: HRESULT;
Size: TSize;
begin
Err := GetThemePartSize(ThemeServices.Theme[teWindow], 0,
WP_CLOSEBUTTON, CBS_NORMAL, nil, TS_TRUE, Size);
I have no idea what the former two functions would return if they worked (the dimensions of buttons for current title bar size or the default title bar size).
The only possible way to get an accurate result seems to be to use the WM_GETTITLEBARINFOEX message. But there's a drawback; it works only for Vista and up. You may need to define the message and the struct it uses depending on the Delphi version you use (D2007 here).
const
CCHILDREN_TITLEBAR = 5;
WM_GETTITLEBARINFOEX = $033F;
type
tagTITLEBARINFOEX = record
cbSize: DWORD;
rcTitleBar: TRect;
rgstate: array[0..CCHILDREN_TITLEBAR] of DWORD;
rgrect: array [0..CCHILDREN_TITLEBAR] of TRect;
end;
TITLEBARINFOEX = tagTITLEBARINFOEX;
TTitleBarInfoEx = tagTITLEBARINFOEX;
PTitleBarInfoEx = ^TTitleBarInfoEx;
...
var
TitleInfo: TTitleBarInfoEx;
begin
SendMessage(Handle, WM_GETTITLEBARINFOEX, 0, NativeInt(#TitleInfo));
Then, you can get the size for the close button from the rect TitleInfo.rgrect[5]. See "TITLEBARINFOEX structure" for details. Notice the values are in screen coordinates.
If you need to support XP and/or below, I suggest you to use the good old GetSystemMetrics(SM_CXSIZE) and GetSystemMetrics(SM_CYSIZE) ("The width of a button in a window caption or title bar, in pixels"). You'd need to workout some approximations depending on if themes are enabled, if aero is enabled etc..
I think SystemParametersInfo with SPI_GETNONCLIENTMETRICS is what you're looking for. I guess the minimize and maximize buttons use NONCLIENTMETRICS.iSmCaptionWidth while close uses iCaptionWidth to determine width.

How do I display a tooltip for a CMFCRibbonButton in the status bar?

I have a CMFCRibbonStatusBar in my mainframe to which I add a CMFCRibbonButtonsGroup which again has a CMFCRibbonButton. This button has the same ID as a menu entry.
Creating the button is done as follows:
CMFCRibbonButtonsGroup* pBGroup = new CMFCRibbonButtonsGroup();
CMFCToolBarImages images;
images.SetImageSize(CSize(32, 16)); // Non-square bitmaps
if(images.Load(IDB_STATUSBAR_IMAGES))
{
pBGroup->SetImages(&images, NULL, NULL);
}
m_pStatusButton = new CMFCRibbonButton(ID_STATUS_SHOWSTATUS,
_T(""),
IMAGEINDEX_DEFAULTSTATUS);
pBGroup->AddButton(m_pStatusButton);
m_wndStatusBar.AddExtendedElement(pBGroup, _T(""));
I want to use this button as a status indicator.
I want to display a tool tip in the following two cases:
when the status changes and
when the user moves the mouse over the button.
I have no idea how to start in the first place. I have looked at the ToolTipDemo and DlgToolTips sample projects but couldn't figure out how to do it since all they do is display tooltips for the toolbar items or dialog buttons (CWnd-derived instead of CMFCRibbonButton).
If you are familiar with the ToolTipDemo sample project: Since there seem to be several ways of doing things, I would prefer the tooltip to look like the "Extended Visual Manager-based" tool tip as shown in this screenshot.
Thanks!
I don't think it's possible to show the tooltip without the mouse cursor being over the control. That's all done automatically.
However if you want to have a nice looking tooltip like in your screenshot, you need to call SetToolTipText and SetDescription, like this:
CMFCRibbonButton* pBtn = new CMFCRibbonButton(12345, _T(""), 1);
pBtn->SetToolTipText("This is the bold Title");
pBtn->SetDescription("This is the not-so-bold Description");
pGroup->AddButton(pBtn);
I am using CMFCRibbonButton controls within a CMFCRibbonButtonGroup, which is added to the CMFCRibbonStatusBar. Take note of the 4th parameter in the CMFCRibbonButton() constructor, bAlwaysShowDescription, as this seems to affect the behavior depending upon whether SetDescription() has been called.
Specifically, if SetDescription() has not been called, it doesn't matter whether bAlwaysShowDescription is TRUE or FALSE - the tool tip is displayed (as I would expect). If SetDescription() is set and bAlwaysShowDescription is FALSE, when hovering over the button the tool tip is displayed with the description below it.
What seems counterintuitive given the name of this bAlwaysShowDescription parameter, is that when this is TRUE and SetDescription() is set, NEITHER the tool tip nor the description appear. I wonder if this is related to this post:
https://connect.microsoft.com/VisualStudio/feedback/details/399646/cmfcribbonbutton-wont-show-tooltip-if-balwaysshowdescription-1
Hope this helps and you can achieve what you need with the different combinations of bAlwaysShowDescription parameter and whether SetDescription() is set.

Programmatically change combobox

I need to update a combobox with a new value so it changes the reflected text in it. The cleanest way to do this is after the comboboxhas been initialised and with a message.
So I am trying to craft a postmessage to the hwnd that contains the combobox.
So if I want to send a message to it, changing the currently selected item to the nth item, what would the postmessage look like?
I am guessing that it would involve ON_CBN_SELCHANGE, but I can't get it to work right.
You want ComboBox_SetCurSel:
ComboBox_SetCurSel(hWndCombo, n);
or if it's an MFC CComboBox control you can probably do:
m_combo.SetCurSel(2);
I would imagine if you're doing it manually you would also want SendMessage rather than PostMessage. CBN_SELCHANGE is the notification that the control sends back to you when the selection is changed.
Finally, you might want to add the c++ tag to this question.
A concise version:
const int index = 0;
m_comboBox.PostMessage(CBN_SELCHANGE, index);
What might be going wrong is the selection is being changed inside the selection change message handler, which result in another selection change message.
One way to get around this unwanted feedback loop is to add a sentinel to the select change message handler as shown below:
void onSelectChangeHandler(HWND hwnd)
{
static bool fInsideSelectChange = 0;
//-- ignore the change message if this function generated it
if (fInsideSelectChange == 0)
{
//-- turn on the sentinel
fInsideSelectChange = 1;
//-- make the selection changes as required
.....
//-- we are done so turn off the sentinel
fInsideSelectChange = 0;
}
}
if you fx want to change the title - which is the line shown when combobox is closed, then you can do following:
m_ComboBox.DeleteString(0); // first delete previous if any, 0 = visual string
m_ComboBox.AddString(_T("Hello there"));
put this in fx. in OnCloseupCombo - when event close a dropdownbox fires
ON_CBN_CLOSEUP(IDC_COMBO1, OnCloseupCombo)
This change is a new string not a selection of already assigned combobox elements