Trace32 use a macro in TEXT or HEADER for window - trace32

here with another Trace32 question. A week ago, I wrote a new script that can run any command that my company uses from one central location. It works great when I remember what workspace I am working in (since all file locations are relative to the workspace root) I have the following code implemented today:
PRINT "Workspace is &WORKSPACE"
; Select the action we want to perform.
DIALOG
(
HEADER "Select A Task To Run"
; Large menu below
I have already forgotten to check the debug console more than once and was left scratching my head when I forgot to change workspaces. I want to do something like the following:
; Select the action we want to perform.
DIALOG
(
HEADER &WORKSPACE
But this doesn't compile. Trying HEADER "&WORKSPACE" doesn't work either as the title just says "&WORKSPACE" instead of giving me the actual file location (C:\Files\Whatever\). Is there a way to use a macro or variable to set the window title to a custom string? I can't seem to find a solution. Thanks!

This is a nice one! Good news: There is a solution. (But it is tricky. Easy alternative solution in the end.)
The thing is, that the macro replacement of the PRACTICE scripts work everywhere inside the actual PRACTICE code. However the dialog description is no PRACTICE code: The dialog description is just embedded inside the script. This is like embedding an image (e.g. via a data-URI) in a HTML file. The image is also not HTML.
The command to show a custom dialog is DIALOG.view <dlg-file>. However the DIALOG.view can also be used with an embedded block (in round braces, which are in separate lines). That is what you do.
And here comes the trick: If you replace the opening brace with (&+ all words starting with & inside the whole embedded block are replaced with a PRACTICE macro - as long as a macro with that name exist.
So here you go:
PRINT "Workspace is &WORKSPACE"
DIALOG
(&+
HEADER "&WORKSPACE"
; Large menu here...
)
Be aware that the macro replacement appears then really everywhere in the DIALOG block. This can cause unwanted side effects - especially if you have embedded PRACTICE code in your DIALOG. E.g.:
DIALOG
(
BUTTON "Push me"
(
PRIVATE &myfile
DIALOG.File.open *.txt
ENTRY %LINE &myfile
PRINT "You picked file '&myfile'"
)
)
If you enable now macro replacement for the Dialog-block it would also replace the &myfile of the PRIVATE and ENTRY command, which is usually not what you want.
However it should work if you explicitly disable macro replacement down to the PRACTICE script embedded in the DIALOG with "(&-". So you get:
DIALOG
(&+
HEADER "&WORKSPACE"
BUTTON "Push me"
(&-
PRIVATE &myfile
DIALOG.File.open *.txt
ENTRY %LINE &myfile
PRINT "You picked file '&myfile'"
)
)
Other workaround would be to define a macro &myfile which actually contains the text "&myfile":
LOCAL &WORKSPACE &myfile
&WORKSPACE="Select A Task To Run"
&myfile="&"+"myfile" // <- This is the trick!
DIALOG
(&+
HEADER "&WORKSPACE"
BUTTON "Push me"
(
PRIVATE &myfile
DIALOG.File.open *.txt
ENTRY %LINE &myfile
PRINT "You picked file '&myfile'"
)
)
If you've mastered this thing you are close to be a PRACTICE master!
Here is another more easy solution for customizing both the TEXT and HEADER of a custom dialog:
Replace the HEADER statement inside the DIALOG description with a WinPOS command before the DIALOG command.
Replace the TEXT statement inside the DIALOG description with DYNTEXT and set the text outside the DIALOG description with DIALOG.Set
E.g.:
PRIVATE &myheader &mytext
&myheader="Select A Task To Run"
&mytext="zaphod beeblebrox is an awesome frood"
WinPOS ,,,,,,,"&myheader"
DIALOG
(
POS 0 0 30. 1
DlgText1: DYNTEXT ""
)
DIALOG.Set DlgText1 "&mytext"
This 2nd approach simply avoids macro replacement inside the DIALOG description. So it is not an exact answer to the question, but maybe a better solution to the actual problem.

Related

newbie: Code to show/hide a STATIC TEXT object in Visual C++ MFC app

I ran into a newbie problem with my first VC++ MFC app (actually, I ran into many problems, but RTFM and DuckDuckGo helped to solve them without crying here for help. Except this one!). Bear in mind that I am playing with this as a tutorial for myself, kind of a learn by example project, and I have a few years of Win GUI app programming experience in Deplhi/Lazarus, and now I am attempting to transition into VC++, simply for my own curiosity. While I am also good with C language programming, I have significantly less experience with C++. So the new programming environment and the less-known language together pose as my obstacle.
Here is what I did:
In a recently installed Visual Studio 2019 Community with only the Windows App development in C++ components selected, started a new project, chose C++ MFC App (Build apps with complex user interfaces that run on Windows.). Set application type to Dialog based, turn off all User Interface Features so only Thick frame is checked (unchecked System-menu, unchecked About-box), turn off all Advanced Features so only Common Control Manifest is checked (unck Printing and print preview, unck Activex controls, unck Support Restart Manager), clicked FINISH.
This prepared me an app with a single small main window, OK and Cancel buttons in its lower-right corner, and a STATIC TEXT item in the middle-center reading something like "TODO: add your own items here". Project name is TutMFC01p.
My goal was to hide that STATIC TEXT when I click one of the buttons, and make it visible again when I click the same button again.
It took me some time to realize that I should not fiddle with the OK and Cancel buttons to add them this functionality, and clicking either of these two buttons also quits my app (hence, no chance to click again). So I placed a new button on the dialog and worked with that instead. Clicking my button while my app was running did absolutely nothing - which was exactly what I wanted.
Double-clicking my button in the Dialog Editor dropped me into Source Editor with a new function autogenerated at the bottom of TutMFC01pDlg.cpp.
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
}
Allrighty, so this is where I will add the code of what the button is supposed to do.
It also injected an ON_BN_CLICKED line to the MESSAGE MAP, which now looks like this.
BEGIN_MESSAGE_MAP(CTutMFC01pDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CTutMFC01pDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
Allrighty again. So this is the way to tell the system that clicking my button should run the code given in CTutMFC01pDlg::OnBnClickedButton1().
The way I first tried to complete my goal was to alternate the STATIC TEXT object between the TRUE and FALSE value of the VISIBILE property upon the click of my button. A Delphi/Lazarus way of doing it is a single line of code like mainform.mystatictext.visible := not mainform.mystatictext.visible but I was not able to find a way to directly reference the property of an object and change its value with a simple assignment operation. What I found instead is that the way to hide objects is using the ShowWindow() method. I also run into difficulties trying to point this (or any other) method to the STATIC TEXT object, because apparently it has an ID of IDC_STATIC, which, apparently, cannot be referred to, as all static objects have this same ID. To simplify the task ahead, instead of hiding the STATIC TEXT I settled for hiding the button itself, and ended up with this code:
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE); //or SW_SHOW
}
This compiles and works very well. Obviously, once the button is pressed and disappears from the window, there is nothing to press again in order to unhide what was hidden. So I tried to move on from this already working code and modify it to act on the STATIC TEXT instead of the button itself. Logic suggested (my logic, anyways) that in order to gain the ability to refer to the ID of the STATIC TEXT, I need to assign a different ID to the STATIC TEXT. Something I can refer to. Something other than the not referrable IDC_STATIC. So I selected the STATIC TEXT object on the Dialog Editor, and in its Property palette I changed the value of the ID property from IDC_STATIC to IDC_STATIC1. This strangely has also changed the NAME property of the object to IDC_STATIC11. Earlier the NAME was IDC_STATIC1. Then in the code of OnBnClickedButton1() I replaced IDC_BUTTON1 with IDC_STATIC1, but that fails to compile complaining that there is no such object. Same happens when tried with IDC_STATIC11.
A little experimenting revealed another phenomena I am unable to explain (or understand). Similarly to how I changed the ID of STATIC TEXT, with my button selected in the Property Editor, I changed its ID from IDC_BUTTON1 to IDC_HideBtn. This also changed its NAME property.
Saved All, rebuilt project, and clicking my button still made it disappear, exactly as it was working before. HOWEVER, the source code of OnBnClickedButton1() and the MESSAGE MAP did not get updated to refer to the new ID, IDC_HideBtn, they still refer to IDC_BUTTON1, same as before.
void CTutMFC01pDlg::OnBnClickedButton1()
{
//TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE);
}
But at this point, IDC_BUTTON1 should be a non-existing ID. Compile should fail. Yet it compiles fine, and it works fine.
QUESTIONS:
Why does the code compile and work with IDC_BUTTON1 in the source while the ID of the button is now IDC_HideBtn?
What can I do to be able to address the STATIC TEXT item as the argument to GetDlgItem() the same way as I could do with IDC_BUTTON1?
If STATIC TEXT items are not supposed to be programmatically changed then what other kind of item could I use instead? In Delphi/Lazarus there is a LABEL object similar to STATIC TEXT, but designed to get different Caption or other values many times while the program runs. In the toolbox of the Dialog Editor I see nothing like that, only STATIC TEXT. Or should I use an Input field instead, to display text in the dialog window?
Is there a way to implement the button click method in the way I initially tried to do the Delphi/Lazarus way? Changing the target object to visible from hidden, and to hidden from visible. Preferrably as a one-liner.
Is there NO WAY to directly refer to the property of an object and change its value with an assignment operation? Or only I did not find it how?
I have some small corrections (as I think), and I wanted to issue them as comments, but according to the comment policy it is better to post an answer despite that the answer has already been given.
Question 2:
It's strange that VS didn't add a new define for IDC_STATIC1 in resource.h on renaming a CStatic component (after all VS created a new id for a new button).
But of course, manual editing of resource.h is a very frequent procedure during programming with MFC, but it is necessary to update the _APS_NEXT_CONTROL_VALUE (and much less often _APS_NEXT_COMMAND_VALUE ) definition so that it points to a new correct value (not equal to previous definitions).
Question 3:
But you can write in you .rc file something like this:
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_MidTextObj,13,96,300,8
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
and then in CTutMFC01pDlg.cpp:
void CTutMFC01pDlg::OnBnClickedHidebtn()
{
if (CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj))
pMyStaticObj->ShowWindow(!pMyStaticObj->IsWindowVisible());
}
Question 4:
Also you can use the the DoDataExchange mechanism for getting/setting text for components like CStatic, CEdit, etc., and you can use ON_UPDATE_COMMAND_UI macros for enabling/disabling components.
But the basic way is to get a component as a CWnd class:
CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj)
or get the component explicily:
CStatic* pMyStaticObj = static_cast<CStatic*>(GetDlgItem(IDC_STATIC1));
(don't use dynamic_cast here)
and then call methods of this fetched instance.
Thanks to the comments my question received, I could refine the direction of my web searches and also examine other files in my project folder to identify where trouble originates from, and understand how pieces of my MFC app fit together. Also, sometimes the inner workings of Visual Studio 2019 require a little manual editing help.
ANSWER 1)
All those IDC_xyzwq identifiers I can assign to the object in its property palette (values are selectable from a list) are predefined macros pointing to their respective numeric value. These live inside the resource.h file of the project. Unfortunately, VS2019 never allowed me to open this file as readable text - it always complained that the file is already open and asked me if I want to close it instead. To study the contents, I actually had to close my VS2019 solution, and open the resource.h file in a text editor. Here is what I found in there:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_BUTTON1 1002
#define IDC_ButtHide 1002
#define IDC_HideBtn 1002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
So it seems that each time I invented a new ID for my button and entered it in the Property Palette, VS2019 injected a new macro definition into the resource file, assigning it to the same numerical value of 1002. But other than auto-creating such entries, Visual Studio performs no maintenance on them and it is the responsibility of the programmer to keep order there. Which requires that the programmer understands what is what, and where it is stored in the project files.
So, even though my button object already had the ID value of IDC_HideBtn in its Property Palette, the earlier IDs of IDC_ButtHide and IDC_BUTTON1 were still valid and referred to the same numeric value of 1002, hence the source code using the old ID compiled, and the button worked fine.
Mind you, I also had to manually replace the button ID NAME to the chosen one in my apps MESSAGE MAP in TutMFC01pDlg.cpp before Visual Studio could reopen my solution/project. See the next section of my answer too.
ANSWER 2)
IDC_STATIC being a peculiar ID with some special treatment, I cannot just invent and type-in any new name into the ID property field of my STATIC TEXT item. More precisely, I actually CAN invent any new ID and enter that into the property field, but Visual Studio DOES NOT automatically generate the corresponding new macro definition in resources.h, most likely because it does not know what numeric value to assign to an object that is supposed to have no numeric value (as it was supposed to have the special value of -1). So instead of entering a new name in the ID property field, the programmer should close the solution, and manually edit the resources.h file in a text editor. YES, against all warning and discouragement in Microsoft Documentation and by seasoned developers, in this particular case it must be done manually. (Or at least, I do not know a better way than directly editing the resource file as text.) Here is what I changed my macro definitions to, by removing the two obsolete and unwanted button identifiers with the value of 1002, and manually adding a new definition entry intended for my STATIC TEXT item - with a numeric value that was not in use by any other entry. In my case, 1001 was not yet used, so that is what I assigned to my invented ID of IDC_MidTextObj.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_HideBtn 1002
#define IDC_MidTextObj 1001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
With these changes saved in resource.h I could close my Text Editor and reopen the solution/project in Visual Studio. Then I could select the STATIC TEXT item in the UI Editor, and in its Property Palette, in the field of the ID property, I could drop down the list of values and select my prepared value of IDC_MidTextObj. Mind you, there is another way to do this, by manually editing the .rc file of the Dialog. Which you will likely need to do for other reasons anyway. See next section of my answer.
ANSWER 3)
Here is the relevant part of my TutMFC01p.rc file.
IDD_TUTMFC01P_DIALOG DIALOGEX 0, 0, 320, 199
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_CLIENTEDGE | WS_EX_APPWINDOW
CAPTION "My VisualC++ Tutorial App 01"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_STATIC,13,96,300,8
LTEXT "Hello MFC!",IDC_STATIC,22,33,86,8,WS_DISABLED
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
I could just change the line starting with CTEXT and replace IDC_STATIC with IDC_MidTextObj to make sure that the STATIC TEXT item uses my pre-created value.
ALSO, if you look carefully, you see that the next line defines another STATIC TEXT item (a new static text item I added to the window in the Dialog Editor). But this is LTEXT instead of CTEXT. Without peeking at this code as text, I would not have known that there are these two different types. Maybe LTEXT is what I was after. I will see what I find about this in the documentation.
ANSWER 4)
Not as a one-liner. See also the next section of my answer for details. But it can be done with multiple lines of code, calling methods to first query the current state of visibility of the object, then hide it if it is visible, or show it if it is hidden.
ANSWER 5)
NO, there is no way to do that in VC++. It works in other languages, but in C++ you have to call functions/methods. See answer from Mark Ransom at the bottom of a similar issue.

How to stop Clion tab key behaviour

When on a C++ line of code like the following
aType.aMethod(
std::make_shared< T_1>();
^^^^^-- Press tab here
)
Clion tries to move to the next parameter(i guess), but being the only parameter it goes nowhere. I want to have the tab to just insert characters(tab or space that is) and not to try to cycle the cursor among the method parameter. Is there a way to stop this alternative functionality?
I searched to no avail in
Settings|Editor|CodeStyle|C/C++
Thank you
"Try changing the "Next parameter" and "Previous parameter" keybindings to something else than Tab."
– Eldar Abusalimov Jul 5 '17 at 9:02
In addition to the accepted answer, i found that tab was assigned to Next Live Template Parameter Under : Main Menu | Navigate | Navigate in File (This is in the keymap section in settings, not the actual main menu). So when i generated definitions for the methods in my class and it jumped into the cpp if there were any auto generated functions with return initializer; as the method body it would jump to these instead of letting me indent code so i turned that off too and now i can happily implement the methods in order and fix those up when i get to them. Alternatively if you like that setting and want to keep it turned on, Hopefully knowing that you have to tidy up all instances of return initializer; before the tab key will indent code again is useful to you, i found it very confusing.
EDIT: i realise this wasn't part of the original question, but this is where googles top result brought me, so i hope you don't mind me adding this info here as its still related to the tab key doing weird things in CLion.

How can I add a context sensitive help button for a specific dialog control

I have an MFC app (10 year old app), which has context sensitive help for each dialog. I want to add help on a specific combobox, as well as a little question mark button next to this control. Users can either select the combobox and hit F1, or they can click on the button next to the combobox, and it will jump to a help page that is specifically about this combobox, rather than general help for the whole dialog.
In the dialog resource properties, I have set "Context Help" to True.
In the combobox properties, I've set "Help ID" to True.
In myapp.hpp, I have added "HIDC_MYCOMBOBOX = mycombobox_help.htm" to the [ALIAS] section, and included the resource.hm file in the [MAP] section.
Again in app.hpp file, the dialog uses "HIDD_MYDIALOG =
mydialog_help.htm"
Yet selecting the combobox and pressing F1 still brings up mydialog_help.htm, instead of mycombobox.htm.
What am I missing to use a separate help page for the control?
Is it possible to redirect the control to an anchor in the main page? Something, along the lines of...
HIDC_MYCOMBOBOX = mydialog_help.htm#mycombobox
I have added a "?" button to run the following code, but this also doesn't give the context for the control, and just opens the mydialog_help.htm.
HELPINFO lhelpinfo;
lhelpinfo.cbSize = sizeof(lhelpinfo);
lhelpinfo.iContextType = HELPINFO_WINDOW;
lhelpinfo.iCtrlId = IDC_BALANCING_METHOD;
lhelpinfo.hItemHandle = GetDlgItem(IDC_BALANCING_METHOD)->m_hWnd;
lhelpinfo.dwContextId = HIDC_BALANCING_METHOD;
lhelpinfo.MousePos = POINT();
CDialog::OnHelpInfo(&lhelpinfo);

Taking data from a Dialog in Qt and using it in a Ui

So I'm making a text editor using Qt and right now I have a button that opens a dialog called "Format text". I want it to work kind of like the dialog in notepad called "font" where you select a few text attributes from some drop down lists and it shows you what your text will look like. Right now I have it working where you can select the font style, font color, and font size and hit preview and it shows you in a box in the dialog what your text will look like. However, I have a button called "okay" which is supposed to change the highlighted text or the text you are about to type, but I can't figure out how to display those changes on the main window. The .ui files are private and a lot of the already made functions and pointers are the same in every ui file so if I change the ui file to pubic I have to change a whole bunch of things. Can anyway give me a simple answer? I'm trying to do this with as little confusion as possible. More coding and less confusion is better than less coding and more confusion for someone of my skill level. Sorry that this is all one giant paragraph and that I didn't provide any code, but I didn't think the code was necessary, however if you do need some of the code i'd be happy to share it.
Thank you for your help and your time. I hope you all have a nice evening.
QDialog have a signal called finished(), you can connect this signal with your slot. To accomplish your work, pass a QSettings or for simplicity QStringList to dialog settings (responsible for changing font, color ...), the QStringList will save user defined settings, after closing the dialog, iterate through QStringList member to alert Main window.
A pseudo code will look like this
Class Editor:
Editor::Editor()
{
TextSettings textSettings;
textSettings.setSettings(settings); // settings is a member
connect(textSettings, &finished(int)), this, SLOT(alertEditor(int)))
}
Editor::alertEditor(int s)
{
if(s == 0)
{
for (int i = 0; i < settings.size(); ++i)
settings.at(i).toLocal8Bit().constData(); // extract various user settings
}
}
Class TextSettings:
TextSettings::TextSettings(QStringList settings)
{
settings << ui->combobox->currentItem(); // font name as example
}

Change Caption of Label

I want to change caption (text) of a label in the execution time depending on user input. If user presses a button, my program will execute some stuff and write the output into a label. But I have a problem about this.
First, there's no label in my environment. At least in toolbox. I know, adding from toolbox is not the only way, but I'm a bit scared to touch the old source code and mess things up.
I found a static text element, but I guess because of its a "static" element, I can't see it in resource.h. So, if I use a function like GetDlgItem(IDC_STATIC);, it doesn't work. Because there's no IDC_STATIC in my resource.h.
This was the second one.
And, I used SetDlgItemText(IDC_STATIC, "text");, too. However, because of my resource.h doesn't know what IDC_STATIC is, I get errors.
Is there a label class/element that is not in toolbox? I guess my IDC_STATIC is not in my resource.h because of its static behavior. Or, is there any other way to update the text of a label/static text?
Thanks for your help.
You want to use a static control, but give it some identifier other than IDC_STATIC. Then you'll be able to use GetDlgItemText, SetDlgItemText, etc., with that identifier. Alternatively, you could/can use an EDIT control set to read-only, which is pretty much equivalent to a static control1.
1Even more than many realize -- for example, to change the background color of a normal edit control, you respond to WM_CTLCOLOREDIT. To change the background color of a static control or read-only edit control, you respond to WM_CTLCOLORSTATIC.
Change the ID of your static text to something other than IDC_STATIC, and change those codes to update it. I wish I tried this 5 mins ago.
Changing the ID of it updates your resource.h and adds your static text in it.
This might help people after me in debugging I guess:
TCHAR *pszBuffer = new TCHAR[255];
pszBuffer = TEXT("dkjhasja");
CWindow wndSys;
wndSys.Attach(GetDlgItem(IDC_BLABLABLA));
wndSys.SetWindowText(pszBuffer);
wndSys.Detach();