I was wondering how Visual Studio associates MFC CDialog derived classes with their corresponding dialog resources. I'm not interested in how the connection is made at run time (as asked here), but rather at design time.
When I add a message handler to a dialog, how does it know which class to add the handler to.
Also, is it possible to have several CDialog derived classes associated with the same dialog resource and vice versa?
I have searched the project directory for the IDD_SOMEDIALOG string but have only found it in SomeDialog.h, resource.h and Project.rc in the expected places so I guess it somehow deduces the connection from those files, most likely the enum in SomeDialog.h:
// in class CSomeDialog:
enum { IDD = IDD_SOMEDIALOG };
I'm asking this mostly out of curiosity.
It depends on what version of dev studio.
In VS6 it was all kept in the CLW (Class Wizard File).
In newer versions of dev studio it doesn't use the CLW anymore and I don't know specifically how it knows, but i suspect its a live parsing instead of using a cached CLW.
As for having multiple derived dialogs using the same resource, it can be done manually. You can duplicate the created class files and rename them and remove the enum from header and edit the use of the IDD enum in the source file to be the actual dialog resource id (IDD_SOMEDIALOG).
AFAIK Dev Studio will only 'happily' handle one class to a dialog at a time. In my experience trying to re-use a dialog resource like this just ends up in a bit of battle with MFC & Dev Studio since they were not intended to do this.
To add to Ruddy's answer:
I noticed that some of my dialog classes in which I replaced the enum { IDD } with static const int IDD was not any longer associated with its dialog resource. Reverting to the enum re-associated them. So it seems that visual studio parses the source code to determine the relationships.
As for resource sharing, it would be ambiguous as to which class should receive the event handler code. Class sharing seems to be be impossible since it relies on the IDD which can not be assigned to a IDD_SOMETHING and IDD_SOMETHING_ELSE simultaneously.
Related
I tried to enumerate all Win32 children of the Desktop handle, then tried to print out each child's class name using GetClassNameW(childHandle).
The chrome browser's class name is "Chrome_WidgetWin_1". However, the Edge browser's class name and Visual Studio Code's class name are also "Chrome_WidgetWin_1".
Why is that so? Why does Microsoft decide to use the same class name as Chrome for them?
Window classes registered without CS_GLOBALCLASS in different processes are technically not the same classes even though the names might be the same.
These class names are internal details that you should not rely on but in this case they are the same because they are all using Chromium based browsers to drive their UI. Visual Studio Code is an Electron app (uses Chromium) and it is well known that Edge changed from custom Microsoft code to Chromium.
I am not sure how to use Application Setting with custom user types.
For example, in a time tracking system, I would like to have an application setting (with application scope) that says how many hours a day an employee must account for. There is a custom user type, TimeQuantity, with some factory methods and a constructor with a signature of TimeQuantity(double, TimeSliceUnit), where the unit is just an enum.
I can get the settings designer to recognize the TimeQuantity type, but am at a loss as how to provide the setting value (8d hours, here).
Must I create some sort of settings provider? Build the object outside of the designer? Roll my own settings infrastructure?
Cheers,
Berryl
I was just battling the same issue. As far as I can tell, visual studio doesn't allow you to browse to a type in your current project; you can only browse to types in a referenced assembly. However, you can type the fully qualified name of the type you want to use in the settings 'Select a Type' dialog box like shown below. Note that this won't work until your project has been built with the type you want to reference already included. (Same is true with referenced assemblies.) Hope that helps!
I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.
Simple question - I found two ways to add a tool window to Visual Studio (2008): create an addin or create a package.
(Addin: http://www.codeproject.com/KB/dotnet/vstoolwindow.aspx)
(Package: http://msdn.microsoft.com/en-us/library/bb165051.aspx)
What's the "right" way?
You can do either, and I've done both. In some ways, addins are a bit easier, but they suffer from some annoying drawbacks.
Add-in:
+No requirement to install the Visual Studio SDK
+No requirement to use a Package Load Key (PLK) or sign your distributed binaries
+Easier development process when you use the Extensibility API (simplified code in many ways)
+Easier installation process (no wacky registry stuff)
-Doesn't seem to behave as well as VSPackage-based tool panes
-I've run into performance issues which prompted me to use the VS SDK COM interfaces instead of the Extensibility ones, leading to a significant performance bump. In other words, my "add-in" is now based on the VS SDK and is only really an add-in because it loads via an XML file instead of the registry. (Also, from everything I can tell, the Extensibility interfaces are just a large utility wrapper around the SDK.)
VSPackages:
+You can harness the full power of the VS SDK, both its feature set and (potentially, when carefully used) performance advantage
+Seems to behave more reliably than add-ins
-Requires signed binaries, a PLK, and a complicated installation procedure
-Steep learning curve, and many seemingly simple actions are nasty/convoluted. I now have an assembly providing extension methods to perform "obvious (to me)" actions on the COM interfaces. Between that and experience things have improved over time. There are similar options available to the community, which you should seriously consider if you go this route.
I think 280Z28 was perfectly correct prior VS2010. But now VS2010 and VS012:
Do not require officially signed packages (may only those that go to the Gallery have to);
Thanks to VSIX it can very easily install VSPackages that can also be deployed to the Gallery.
Moreover VS2010 supports another kind of extensibility: those are MEF extensions, that are lightweight plugins that trigger only at specific events of the IDE, like text editor events. An example is FixMixedTabs extension.
Just a create a VSPackage empty package (no menus, commands, ...) and copy this in the main class to create a VSPackage that basically loads when there's an active solution and just get a reference to the DTE2. In this way you can just use it as an Add-in.
// This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
// a package.
[PackageRegistration(UseManagedResourcesOnly = true)]
// This attribute is used to register the informations needed to show the this package
// in the Help/About dialog of Visual Studio.
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[Guid(GuidList.guidVSPackage1PkgString)]
// Load this package when a solution is loaded (VSConstants.UICONTEXT_SolutionExists)
[ProvideAutoLoad("{f1536ef8-92ec-443c-9ed7-fdadf150da82}")]
public sealed class VSPackage1Package : Package
{
/// <summary>
/// Default constructor of the package.
/// Inside this method you can place any initialization code that does not require
/// any Visual Studio service because at this point the package object is created but
/// not sited yet inside Visual Studio environment. The place to do all the other
/// initialization is the Initialize method.
/// </summary>
public VSPackage1Package()
{
Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
/// where you can put all the initilaization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
Trace.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
base.Initialize();
IVsExtensibility extensibility =
GetService(typeof(EnvDTE.IVsExtensibility)) as
IVsExtensibility;
DTE2 dte = extensibility.GetGlobalsObject(null).DTE as DTE2;
}
}
If you are just creating a simple tool window then I suggest going the Add-in route.
Both Packages and Add-Ins are ways of extending Visual Studio. Generally speaking they have the same functionality. Packages are a bit more powerful and allow deeper integration into Visual Studio. But that deeper integration comes with a cost including bigger ramp up times and installation procedures.
Add-ins are designed to be a more light weight extension mechanism. Smaller ramp up time and easier installation.
If all you are doing is tool window with basic interaction of the editor our code model then add-in is the best route.
I'm facing some troubles still while learning, so I guess it tends to get worse once I play with the big kids: warnings in dynamics aren't as precise and informative as VS's, there are no mouse-over tips, and exceptions to show me exactly where I've got it wrong.
I'm just too used to Visual Studio, it's intellisense and all the tools (dynamics is quite new when compared to Visual Studio)
More than solving simple code issues, i'd like to learn how to solve upcomming ones i might have in code not written by me or anything else i'd solve in 3 minutes in Visual Studio, as well as tips on how to survive in dynamics ax without all the Visual Studio tools.
The code editor in Dynamics AX has some intellisense, typing the name of a table or class variable followed by . or :: will give you a list of fields or methods available for that item. After you type the ( to start a method call, a tooltip pops up with parameters available on that method. When starting a new line, you can right click and List Tables, List Classes, List Types, etc. Most of those commands are also available via Shortcut Keys. Note that the intellisense only works if all the code in the method up to the location of your cursor is syntactically correct.
Make sure you have updated the cross reference in your development environment (Tools/Development tools/Cross-reference/Periodic/Update). With an updated cross reference, you can right click an any table, field, class, method, extended data type, or enum in the AOT and choose Add-Ins/Cross-reference/Used by to see where that item is used in the system.
You can also use Tools/Development tools/Code explorer to view the source to the application with all types, variables, and methods turned into hyperlinks so you can click to go right to the definition of that item.
Another useful tool is Application hierarchy tree, available either under Tools/Development tools, or on the right click Add-Ins menu. This will show you the class hierarchy, so you can easily see, for example, that SalesFormLetter derives from FormLetter, which derives from RunBaseBatch.
In the editor, you can highlight text and right click to Lookup Properties/Methods or Lookup Definition.
If you are trying to track down where in the system a particular infolog message is generated there are two strategies to use:
Set a breakpoint on the first line
of the method Info.add(). Then when
you run the code generating the
message, you will pop into the
debugger as soon as the infolog is
generated. You can then look at the stack
trace in the debugger to see where the code is that
generated the message.
Run Tools/Development
tools/Label/Label editor and search
for the text of the message. Select
the Label ID of the message, then
click Used by to see where that
message is used in the system.
There is also http://www.axassist.com/ which extends intellisense and many other extensions
What these guys said already is very interesting and helpful.
I'd like to add that within AX in real life you are probably working with multiple contexts. e.g. Code running in the client, code running in server, code running in p-code and in IL, COM integrations, Enterprise portal and so on.
My point is, if you want to figure something out through debugging, you must first understand where the code(s) you'd like to debug is running.
Knowing that is important because you might have to allow debugging or give permissions in multiple places.
Examples:
Windows AD debugging users (add yourself)
Allow debugging on client
Allow it on server
Disable IL if you want to use MorphX, otherwise attach the process in VS.
Allow World Wide Web Publishing Service to interact with desktop for EP.
One last thing, you are starting to work with ax right now, perhaps you will need to work with AX7(Dynamics 365 for Operations). This version of the system works only with visual studio. It is still x++, but you have a lot of the things VS provides you.
Take a look on EditorScripts Class,On AX Editor you can use it by right click and choose "Scripts". It is a kind of intellisense that can make by your self, for example: here is my in-line comment whenever I type "mycom" and press "tab"
public void template_flow_mycom(Editor editor)
{
xppSource xppSource = new xppSource(editor.columnNo());
int currentline = editor.currentLineNo();
int currentcol = editor.columnNo();
Source template = "//Partner comment "+date2str(today(),123,2,1,3,1,4, DateFlags::FormatAll )+" at "+time2str(timenow(), 1, 1)+" by MAX - Begin\n";
template+=strRep(" ", currentcol)+ "\n";
template+=strRep(" ", currentcol)+ "//Partner comment "+date2str(today(),123,2,1,3,1,4, DateFlags::FormatAll )+" at "+time2str(timenow(), 1, 1)+" by MAX - End\n";
editor.insertLines(template);
//move cursor to the empty line between the comments
editor.gotoLine(currentline+2);
editor.gotoCol(currentcol+4);
}