I have a simple Win32 project generated by VS 2012. In the resource.h file, I saw this:
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
I found it is been referenced in a couple places in the resource.rc file. But I could not understand what it means. Neither did I find reference about it online. Any idea?
When creating child controls by calling CreateWindowEx, you have to assign a control ID (through the overloaded hMenu parameter). The control ID can later be used to refer to a control, without having to store the dynamically created HWND (e.g. when calling GetDlgItem or GetDlgItemInt).
Some controls rarely need to be identified in code. A prominent example is the Static Control1, that, if defined in a resource script, usually does not need to be referenced in code. You (or the dialog manager) still need to pass a control ID when creating the control, even though you don't use it later on. For those controls you can pass the IDC_STATIC control ID, that is defined in a wizard-generated Resource.h file2.
1 Other examples include the Icon Control (a static control with the SS_ICON style), the Line Control (a static control with the SS_ETCHEDHORZ and SS_SUNKEN styles), or the GroupBox Control.
2 This is not a convention of the Windows API3. It is strictly a decision made by user code. You could use another ID value, or not define IDC_STATIC at all if you want, and use an integer literal in the LTEXT control statement instead: LTEXT "Filename", -1, 10, 10, 100, 100
3 Granted, the SDK header winres.h does define the preprocessor symbol IDC_STATIC as (-1), so if you do define it in your code, make sure to assign the same value to avoid any confusion.
Related
In an MFC program I am trying to access controls that are in one window (class) from another (sibling or daughter) window with code in a different .cpp file. Typically you access a control with a DDX_Control variable defined in the class .cpp file.
DDX_Control(pDX, IDC_STATUS, m_Status);
The code for the other window is in a different file, so I don’t have access to the control variable (m_Status). What I have done is used FindWindow to find the main window, then GetDlgItem to find the control I am interested in:
CWnd * tmpWnd = CWnd::FindWindow(NULL,"MainWindow"); // find the main dialog box
CStatic * tmpStatus = (CStatic*) tmpWnd->GetDlgItem(IDC_Status);
tmpStatus->SetWindowText(“Status Report);
This works fine in the debugger, but fails when executed outside the debugger. FindWindow gets the window ID correctly, but GetDlgItem returns null.
Ideally I’d like to access the control variable (m_Status) from the other window, but I don’ know how to do so. I understand the GetDlgItem is less than ideal under any circumstance.
One solution would be to send a message to the main window class and tell it what to do, but I’d have to have a routine to handle each control and know how to handle whatever kind of data I am sending.
Is there a “right” way to do this?
Thank you
The ultimate answer is to cast to the original class:
((CspDlg *)AfxGetMainWnd())->m_Status.SetWindowText("Report");
Since you created the "main" window you have an object or pointer for it. Or, you can call AfxGetMainWnd() to get a pointer to it. Then you can use that to access a public member such as m_Status. All of your windows are interconnected and it should not be necessary to use FindWindow to find any window in your own program.
The fact that some variables may be defined in another file is not relevant. That can be handled with suitable use of #include "theotherfile.h" and object pointers/references.
I'm working on a Windows app that needs to run on XP, Vista, 7, and 8. I'm trying to set the application icon, and it works, using DI_ICON1 as the tag in my RC file:
DI_ICON1 ICON DISCARDABLE "myapp.ico"
Using IDI_ICON1 didn't seem to do the right thing here.
However, I also create a second window (also at the root level, ie not a child of my app's main window) and the ALT-TAB icon for that second window wasn't showing up correctly; it was just the default, generic app icon. Adding a second line to the RC now made the ALT-TAB icon work:
IDI_ICON1 ICON DISCARDABLE "myapp.ico"
so with both lines everything works. But I don't know why or how or wtf these identifiers even mean. So what are they, where are they defined, and by what magic do they work?
IDI_ICON1 is just a unique name identifying the resource. You can give it any name as long as it is unique. The development environment should generate a Resource.h file that uses a #define preprocessor directive to assign it a 16-bit unsigned integer unique identifier.
See:
https://learn.microsoft.com/en-us/windows/win32/menurc/icon-resource
https://learn.microsoft.com/en-us/cpp/windows/resource-files-visual-studio?view=msvc-170
IDI_ICON1 is probably just a convention that someone came up with, where IDI means "ID Icon", and 1 is because it is the first icon being defined. So, if you were defining another icon you'd identify it with IDI_ICON2. If you were defining a bitmap resource, you would identify it with IDB_BITMAP1.
DISCARDEABLE is only relevant for 16-bit Windows. See: https://learn.microsoft.com/en-us/windows/win32/menurc/common-resource-attributes
I wanted to ask about winApi 32 custom icons creation. When I define icon in recource.h:
#define IDI_MYICON 1
What does that number, in this case 1 mean?
And what about IDI is it just a standard or it actually means something?
1 is the value, IDI_MYICON is just a placeholder for the 1
IDI is an prefix and stands for An Icon or bitmap resource
see this list
Normaly ResourceID's get assigned automaticly by Visual Studio (or other IDE).
So you could use IDI_MYICON instead of using the 1 in your code.
Icons are stored in the resource section of the PE file when it is built. The "1" is the resource identifier for that icon. It doesn't have to be "1" but each icon must have a unique identifier. It's just easier to start at 1 and go up.
IDI is a Microsoft convention to identify an Icon resource. You could actually name it anything you want but sticking with convention will lead to less confusion.
We have an in house button control, and quite frankly it sucks. I'd like to replace it but I don't want to go onto every form in our project and delete/add a new control. It seems to me that if I design a new button that has all the same properties as the old one then I ought to be able to give it the same name as the old one and just replace all the reference lines in the vbp files to point to the new control.
Has anyone tried this (better yet have you heard of a tool that will do it for you) and if so what 'gotchas' should I be on the look out for?
Thanks!
The *.vbp files are one place you'll need to change. There are also references to the used control libraries in the files containing GUIs -- that's form (*.frm), control (*.ctl), and property page (*.pag) files. These files are in a plain text format and you can see the references at the top. They look like this:
Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "mscomctl.ocx"
Those refs will need to be added or updated in all relevant files if the new control is a compiled OCX. If it's in the same project I don't think it needs any reference there, and if it's in a different project in the same project group I'm not sure. Save a test form with the new control to see.
Note that you don't have to keep the same control class name. Inside the *.frm/ctl/pag files, instances of individual controls on them are represented by a simple format like this:
Begin VB.CommandButton Command2
Caption = "Cancel"
Height = 375
Left = 2460
TabIndex = 1
Top = 2400
Width = 1455
End
The syntax of the first line there is "Begin LibraryOrProjectName.ClassName NameOfThisInstance". So, provided the offending control's name is distinctive it should be easy to search & replace references to it both in the BASIC source and in the GUI layouts. You might want a plain text editor that can perform search and replace across multiple files (Notepad++ is one).
Some control properties are stored like this:
Picture = "frmMain.frx":292F
These correspond to the *.frx, *.ctx, and *.pgx files, which contain binary data for the values of certain control properties. I don't think these files should need altering or cause any problems. They don't appear to contain control names.
Use a full compile (Ctrl+F5) to be sure no problems linger in parts of the source afterward.
Never tried it. Good luck.
There is only one tip to be added to the accepted answer.
If you need to replace any generic VB control with 3rd party or custom ActiveX control you must replace the:
BeginProperty Font
with
BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
Omiting to do so results with run-time error 713 when trying to edit/open the form.
If there is no BeginProperty statement in the block then control uses default font and this replacement is not needed.
An additional scenario to look for is if the classes in the OCX are referenced directly in code.
In other words, if the control class was ABCButton then you need to look for ABCButton in all .BAS and .CLS files as well, and make appropriate changes.
Is it possible to determine which property of an ActiveX control is the default property? For example, what is the default property of the VB6 control CommandButton and how would I found out any other controls default!
/EDIT: Without having source to the object itself
I don't use VB, but here it goes.
I found Using the Value of a Control, but it's not a programmatic solution.
If you have access to the code, look for
Attribute Value.VB_UserMemId = 0
using Notepad.
It depends on when you want to determine this. You could print the "value" of, say, a label control (which has no "value" property) to the debugger like:
debug.print "Value for cmdTest is ["+format(cmdTest)+"]"
Which will give you something like:
Value for cmdTest is [False]
As it turns out, the default value for a command button is it's state (pressed or not), so if you put the code example above in the click event for the control, you will see "True", if you execute it somewhere else, you'll see "False".
For other results, this method will at least show you the sort of property you're looking for. You could use:
debug.print "cmdTest's value is of type ["+TypeName(oObject) +"]"
which tell you the actual type, namely:
cmdTest's value is of type [Boolean]
You could use various methods to narrow things down, such as setting the value and seeing what happens.
Use OLE/Com Object Viewer, which is distributed with Microsoft Visual Studio.
Go to type libraries and find the library the control is housed in, for example CommandButton is stored in Microsoft Forms 2.0 Object Library. Right click the library and select view. Find the coclass representing the control and select it:
As can be seen, the default interface for CommandButton is ICommandButton, when you inspect ICommandButton look for a property that has a dispid of 0. The IDL for the dispid 0 property of CommandButton is:
[id(00000000), propput, bindable, displaybind, hidden, helpcontext(0x001e8d04)]
void Value([in] VARIANT_BOOL rhs);
[id(00000000), propget, bindable, displaybind, hidden, helpcontext(0x001e8d04)]
VARIANT_BOOL Value();
Showing you the default property.
you have access to the code, look for
Unfortunetly I don't have access to the code for most of the controls. However the link is useful for the Microsoft Controls, but I still would like a way to know for other controls.