SysLink control - set property Visible in C++ code - mfc

I have a SysLink Control with ID of "IDC_SYSLINK", and the Visible is set to false as default. Based on some logic, it will then be set to True from the C++ code.
In the class CMFCSomeDlg, I defined a member variable m_SysLink of type CLinkCtrl, and link with IDC_SYSLINK by doing the following,
void CMFCSomeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SYSLINK, m_SysLink);
}
I wonder how can I use m_SysLink to dynamically set the Visible property of SysLink control?

Related

How to show an item in listbox is selected without user click (C++ FMX, C++ Builder)?

I am trying to use the SetItemIndex method to programmatically select an item of a listbox. It's a virtual method, so I understand I need to override it, but I'm not sure what that would look like or where I would put the code.
Alternatively, is there another method I should use to show that an item in a listbox is selected?
--
What my app looks like now:
What I want it to look like (without the user clicking):
I'm creating an app using C++ FireMonkey (FMX, using C++ Builder) to get user input from many screens. The listbox is to show the user where they are in the input process, and provide the ability to jump back several screens.
If they use the next button to navigate to the next screen, I want the listbox to automatically show the corresponding screen as selected.
--
Here are the relevant excerpts from my code:
class TFormMain : public TForm
{
__published: // IDE-managed Components
TListBox *leftSideBar_listbox;
}
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
leftSideBar_listbox->SetItemIndex(0);
initializeApp();
}
And the error I get:
[bcc32c Error] TFormMain.cpp(29): 'SetItemIndex' is a protected member of 'Fmx::Listbox::TCustomListBox'
FMX.ListBox.hpp(493): declared protected here
In FMX.ListBox.hpp line 493:
protected:
...
virtual void __fastcall SetItemIndex(const int Value);
relevant documentation:
http://docwiki.embarcadero.com/Libraries/Rio/en/FMX.ListBox.TCustomListBox.ItemIndex
(this post is about C# instead of C++)
Programmatically selecting an Item in a ListBox
Just realized I can set the item index like this:
leftSideBar_listbox->ItemIndex=0;

C++ Winapi HWND Get element by Name

Is there a way I can get a HWND by it's property "name"? I know that every IDE has its own properties for HWND elements but those properties are applied to the HWND.
I'm not working in Visual Studio, this is just a case. I want to get HWNDs by Name in C++ without VS Libraries.
For example:
HWND button = GetHwndByName("button1"); //Example
Property "name" is button1
I'm going to assume you're either trying to access your GUI controls in code or some other program's GUI controls.
As some people have mentioned, the (name) property in the properties editor is just the variable name used for that control. Your screenshot shows Visual Studio editing a .net program. In the case of .net, the (name) field is the name of the class member of the window class that represents the control. So if (name) is button1 then Visual Studio might generate code like
// pseudo-C++/C#-like
class Form1 : public System.Windows.Forms.Form {
private:
System.Windows.Forms.Button *button1;
...
};
The idea here is that you would have event handlers as part of your Form1 class:
void Form1::onButton1Clicked(void)
{
this->button1->SetText("You clicked me!");
}
As such, the (name) is not an intrinsic property of the window from Windows's point of view.
I don't know what CA Plex's GUI editor looks like, but I would assume, given you said you were using C++, that it either
a) produces a class like the one I pasted above, in which case you would just use the (name) directly as members, or
b) produces a header file with each of those control names as global HWND variables
Either way, you can just use them directly from within your code. Perhaps have something like
void doToAllButtons(void (*f)(HWND, LPARAM), LPARAM lParam)
{
(*f)(button1, lParam);
(*f)(button2, lParam);
(*f)(button3, lParam);
}
and simply write an appropriate function to call via this one.
If you need to interface with another program and want to use its variable names, then you're out of luck. You'll need to find the windows you want some other way, such as with FindWindow().

How can I make a button in MFC do something different based on what previous button was clicked?

So I have a C++ program in Visual Studio 2012 with an MFC GUI. I did not build the base of this code, I am modifying pre-existing code that included the GUI.
The program starts with all the buttons but 2 grayed out. What I would like to do is link the grayed out buttons to different functions depending on which of the two non grayed out buttons I click. Right now the buttons are linked to functions in a two step process. I'm pretty sure I want to leave the first step alone and modify the second, but here is both in case I am wrong.
Step 1:
void CTCPClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_VERSION, m_Version);
DDX_Control(pDX, IDC_OPTIMIZE, m_Optimize);
DDX_Control(pDX, IDC_NORMALIZED_SPECTRUM, m_Normalize);
DDX_Control(pDX, IDC_AQUIRE, m_Acquire);
DDX_Control(pDX, IDC_DISCONNECT, m_Disconnect);
DDX_Control(pDX, IDC_ASD_CONNECT, m_Connect1);
DDX_Control(pDX, IDC_OCEAN_CONNECT, m_Connect2);
}
Step 2:
BEGIN_MESSAGE_MAP(CTCPClientDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_VERSION, OnVersion)
ON_BN_CLICKED(IDC_OPTIMIZE, OnOptimize)
ON_BN_CLICKED(IDC_NORMALIZED_SPECTRUM, OnNormalize)
ON_BN_CLICKED(IDC_AQUIRE, OnAcquire)
ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
ON_BN_CLICKED(IDC_CONNECT_1, OnConnect1)
ON_BN_CLICKED(IDC_CONNECT_2, OnConnect2)
END_MESSAGE_MAP()
These are one right after the other near the start of the code. Connect1 and Connect2 are the two buttons that start clickable, then I want the other buttons to link to different functions after I click them (so say if I click Connect2 then Version would go to OnVersion2 and such). It seems like if I could just declare the ON_BN_CLICKED for the other buttons inside the OnConnect1 and OnConnect2 functions I would be good, but I'm not really sure how to do that. I might be focusing in the completely wrong spot too, so any help would be greatly appreciated.
Edit: Forgot to mention I know I can just have a variable that gets set to 0 or 1 or whatever and have each function split by an if statement. But I was wondering if I could do without that, it seemed like it would be cleaner to just have two separate functions entirely. I'm already in the process of setting it up with the variable, but would like to change it if possible.
ON_BN_CLICKED is part of a table that is defined at compile time, listing a button ID and a function. That can't be changed at run time. Just do it in code with a boolean variable in the OnConnect1 message handler.

How to update ToolTip text each time before display?

How can I make a toolTip text updating itself each time the tooltip is (about to be) displayed ?
I have a CDialog derived dialog which uses CToolTipCtrl tooltips in the usual way and it works just fine:
CToolTipCtrl member variable in my CDialog class.
created tooltip and added to tool in CDialog::OnInitDialog
message relayed to the CToolTipCtrl in CDialog::PreTranslateMessage
I also know how to update the toolTip text in various places of the code using CToolTipCtrl::UpdateTipText and CToolTipCtrl::Update
However, what I want and have not yet accomplished is this:
I want that the text of the tooltip updated each time the mouse hoovers over the tool before the according tooltip is displayed, i.e. the displayed text is dependent on the situation the moment the tooltip-text is displayed.
My working code so far (truncated to relevant lines):
class CmyDialog : public CDialog
{
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual void RefreshToolTipText(); // Want to call this prior each display
CToolTipCtrl m_toolTip;
}
BOOL CmyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_toolTip.Create(this);
m_toolTip.AddTool( GetDlgItem(IDC_SOMECONTROLID), "Sometext" );
m_toolTip.Activate( TRUE );
}
BOOL CmyDialog::PreTranslateMessage(MSG* pMsg)
{
if(IsWindow(m_toolTip.m_hWnd))
m_toolTip.RelayEvent(pMsg);
}
void CmyDialog::RefreshToolTipText()
{
m_toolTip.UpdateTipText( "updated runtime text", GetDlgItem(IDC_SOMECONTROLID) );
m_toolTip.Update();
}
When calling CToolTipCtrl::AddTool use the "special" value LPSTR_TEXTCALLBACK as the text to use for the tooltip. This will cause the tooltip to post a TTN_NEEDTEXT notification to the parent of the window you are adding a tooltip for. The parent can then set the text accordingly.
I seem to have figured it out myself. As I couldn't find the solution online, I'm going to post it here for references. I would still appreciate comments if there are any.
I've added the following line the message map of the CmyDialog class:
BEGIN_MESSAGE_MAP(CmyDialog, CDialog)
ON_NOTIFY( TTN_SHOW, 0, OnToolTipTextAboutToShow )
END_MESSAGE_MAP()
And I've added the following member function to CmyDialog:
void CmyDialog::OnToolTipTextAboutToShow(NMHDR * pNotifyStruct, LRESULT* result)
{
if ( pNotifyStruct->hwndFrom == m_toolTip.m_hWnd )
RefreshToolTipText();
}
Apparently, the TTN_SHOW notification code gets send via WM_NOTIFY each time a tooltip is about to be displayed. The if-check in my function checks that the toolTip is from the specific CToolTipCtrl.

Disable/Enable Ribbon Buttons for MFC Feature Pack

I am using the MFC Feature Pack and I have some buttons on a ribbon bar, instances of CMFCRibbonButton. The problem is that I would like to enable and disable some of them in certain conditions, but at runtime. How can I do this? because there is no specific method for this...I heard that a solution would be to attach/detach the event handlers at runtime, but I do not know how...
When you create the CMFCRibbonButton object you have to specify the associated command ID (see the documentation for the CMFCRibbonButton constructor here). Enabling and disabling of ribbon buttons is then done using the usual command update mechanism in MFC, using the CCmdUI class.
For example, if you have a ribbon button whose command ID is ID_MYCOMMAND and you want to handle this command in your application's view class, you should add these functions to the class:
// MyView.h
class CMyView : public CView {
// ...
private:
afx_msg void OnMyCommand();
afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
and implement them in the .cpp file:
// MyView.cpp
void CMyView::OnMyCommand() {
// add command handler code.
}
void CMyView::OnUpdateMyCommand(CCmdUI* pCmdUI) {
BOOL enable = ...; // set flag to enable or disable the command.
pCmdUI->Enable(enable);
}
You should also add ON_COMMAND and ON_UPDATE_COMMAND_UI entries to the message map for the CMyView class:
// MyView.cpp
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_COMMAND(ID_MYCOMMAND, &CMyView::OnMyCommand)
ON_UPDATE_COMMAND_UI(ID_MYCOMMAND, &CMyView::OnUpdateMyCommand)
END_MESSAGE_MAP()
For more information on message maps in MFC, refer to TN006: Message Maps in MSDN.
I hope this helps!
ChrisN gave a pretty perfect answer. You can see an example of exactly how this is done by downloading the VS2008 Sample Pack from here, and opening the MSOffice2007Demo solution.
When running the sample, look at the "Thumbnails" checkbox in the View tab of the ribbon, it's disabled.
This is controlled by CMSOffice2007DemoView::OnUpdateViewThumb which calls pCmdUI->Enable(FALSE);. You can change this to call TRUE or FALSE at runtime to enable/disable the button respectively.