Detecting Quick Access command state - delphi

We have an application that is using Windows Ribbon Framework for an UI. The app itself is written in Delphi and uses Windows Ribbon Framework for Delphi to interface with the ribbon API.
Our ribbon XML places few commands into the Quick Access toolbar. Use can then remove/add commands either by using the built-in ribbon mechanism (selecting the drop/down button and clicking on a command name) or by selecting More commands command which opens the configuration dialog.
The problem I've encountered is that I cannot find a way to get the current state of commands in the QA collection (whether they are visible or not).
In the example above (picture) I would like to detect that first five commands are checked and that the last is not so I can prepare the configuration dialog accordingly.
I have no problems enumerating the IUICollection and accessing the items stored inside. I can also get the UI_PKEY_CommandId for each item. I cannot, however, find a way to read the checked/unchecked state. I tried reading UI_PKEY_BooleanValue and UI_PKEY_Enabled for all items in the collection, but they do not return that state.
I have also tried to monitor IUICommandHandler.UpdateProperty but it doesn't get called when such item is checked/unchecked (except that it is called with the UI_PKEY_Label key).
Does ribbon API even support this functionality?

Related

Installshield 2014 Basic MSI Hide features dynamically not installing features

I have created a Basic MSI Installer using InstallShield 2014 for a server/client program and have to hide features dynamically based on the License Key of a database that is installed prior to our Server app being installed. I have created conditions for the features that need to be hidden, setting the InstallLevel to 0 if they are not licensed and 1 if they are licensed. I am getting the license key after the SQL Login dialog (because the installer wouldn't know what database to look in otherwise) but conditions are evaluated during the CostFinalize action, which runs before the dialogs are created. So after I get the license key and run some other custom actions to determine the availability of each feature, I call the CostFinalize action before the CustomSetup dialog is shown.
I am getting the correct behavior for the features that need to be shown, and you can select or deselect said features in the dialog, however, when the installation executes, the selected feature is not installed....and the log file says that the feature is not selected for install, even though the user clearly selects it. Why would this be happening? Is there another approach to hiding features dynamically (I have tried the FeatureSetData function in an InstallScript action, but to no avail)?
Also, after I added the conditions to the features, whenever I try to uninstall the program from the Programs and Features app, I get an Error 1606 Could not access network location. It's like the registry key gets messed up when there are conditions on the features...Any help would be greatly appreciated.
I found the problem...If you set the features InstallLevel to 0 to start with and have a condition that sets it to something greater than zero, then it will not install the feature, regardless of whether it's selected. If you invert this logic and start with the features InstallLevel set to 1 and have a condition that changes the installlevel to 0, it will hide or show the feature AND it will be installed properly. This also caused the error 1606 I was getting on the uninstall...
Also, if anyone ever has components that get installed that aren't supposed to be installed, then you might try switching the Dependency Checking to none. For some reason, the .NET dependency check that InstallShield does causes certain components to install all the time, even if their assigned feature is turned off. Hope this helps someone in the future.
The CostFinalize can also be run by a dialog to refresh the feature list. Here are the steps:
In the Next PushButton of the SetupType Dialog, create a new item at the top.
Event: DoAction
Argument: CostFinalize
Condition: 1=1
In my case, I was hiding a feature based on a previous dialog and needed it to reevaluate conditions in the Program Feature.
Condition: Level:0 GLOBAL_VAR=0
Condition: Level:1 GLOBAL_VAR=1

Tab order in a console app with a single VCL form

I have a Windows console app created with Embarcadero XE 6 (in fact converted from a Borland C++Builder5 project). It has a single form with a few buttons and edit controls. All these controls have set TabStop=True and appropriate TabOrder's. However, pressing Tab in runtime when the form is shown does not do anything (it just produces a sound when a cursor/focus is in an Edit control and does nothing when a button is focused).
I have read in docs that Tab order would not work unless the Parent of the form is set. However, this is the only VCL form (the other windows are the console and the GLUT window), so there is no VCL parent AFAIK. I tried to set
Parent=Application->MainForm;
in the Form's constructor, but the Application->MainForm is also NULL. Any ideas?
Your problem is that you don't have a message loop. This is because console applications are not expected to have windows and do not come with message loops by default.
You can run a message loop by calling:
Application->Run();
However this will probably stop the console part of your application from working properly. How can your main thread service the console synchronously and the asynchronous GUI message loop at the same time?
I suspect you will need to have a more serious re-think of your application design.
Regarding your update, it seems that you do have a message loop, but it is the message loop for the GLUT framework. The VCL framework requires its message loop to handle dialog messages like TAB key presses.
It's plausible that running the VCL message loop in place of the GLUT message loop would give better results. But it's quite likely that would just break the GLUT part of the app.
Trying to run two incompatible GUI frameworks out of a single message loop is hard to get right. There's probably no quick fix here. You'll need to dig deeper. Perhaps it would be best to give up on the VCL and stick to the one GUI framework.

Windows installer self-healing using ProvideComponent

I have an application(app1) that uses another application(app2)'s DLL to do some things. The problem is that I need to have some current user registries set for the DLL to work. If I call app2 from the advertised shortcut it will invoke windows installer self-healing and populate its registries. However if I've just installed app2 from another user,logged in for the first time, and used app1 it will fail as the DLL will not have it's registries populated.
With this in mind I tried to use the Self-Invoked Resiliency method to trigger MSI self-healing.
The "HKCU" feature is the top feature containing a single component "HCKURegistry" which only contains registry keys. The keypath for the "HCKURegistry" component is a key in the HKCU hive.
I'm using Delphi XE3 and here is the line of code:
szProductCode :='{293A0959-6ECF-4026-929B-ECC777934525}';
szComponent:= '{45282475-634F-4222-81BA-030FA63703BD}' ;
MsiProvideComponent(pwidechar(szProductCode),pwidechar('HKCU'),pwidechar(szComponent),INSTALLMODE_DEFAULT, lpPathBuf,#pcchPathBuf);
When, however, my app1 executes this line the Windows Installer displays a windows installer "Preparing to install..." window and stays like this forever. If I click "Cancel" it says "Canceling..." and stays like this until I kill the app from the task manager.
The Event log shows two items:
Detection of product '{293A0959-6ECF-4026-929B-ECC777934525}', feature 'HKCU', component '{45282475-634F-4222-81BA-030FA63703BD}' failed.
Detection of product '{293A0959-6ECF-4026-929B-ECC777934525}', feature 'HKCU' failed during request for component '{45282475-634F-4222-81BA-030FA63703BD}'
A possibly relevant information. When I trigger the self healing the normal way I get the same two lines but the second one has additional sentence (the keypath registry key for the component):
Detection of product '{293A0959-6ECF-4026-929B-ECC777934525}', feature 'HKCU', component '{45282475-634F-4222-81BA-030FA63703BD}' failed. The resource 'HKEY_CURRENT_USER\Software\MyData\SomePath' does not exist.
I moments of desperation I tried using:
res:=MsiReinstallFeature(pwidechar(szProductCode),pwidechar('HKCU'),REINSTALLMODE_USERDATA);
And swapping INSTALLMODE_DEFAULT for REINSTALLMODE_USERDATA in the MsiProvideComponent call. Both behaved differenty in that they did not put anything into the Event log. Otherwise they both stuck in "Preparing to install..." just as the original call...
I'm stuck on this for a while now. Can someone spot what I'm doing wrong?

ActiveX Control always working on my machine - unpredictable behavior on others?

I have a question about my ActiveX control not always working in IE on other machines.
Context: I'm working on an internal app for my company. It is designed to be a standalone web-page config tool for viewing a static customized version of our web app. The user may select the colors, images, and other settings they would like to see, and these will be present in the static mockup/preview version on their machine when they click a button.
Implementation: my javascript file creates a filesystem/activex object that essentially creates a temporary javascript file to which a list of values are written. Then when the user previews the configuration, the javascript file is located and values are loaded dynamically into the dom, etc etc. Naturally this functionality only works in Internet Explorer and is shady at best, but is my only way of implementing a purely zero configuration, client-side dynamic webapp.
Problem: When I test out my script, Internet Explorer prompts me twice about ActiveX controls and I say "yes" to them and the ActiveX functions work. I do this every single time I open my page. But sometimes when I send the file to another person so they can use it, they don't get the notifications so it doesn't work. However sometimes they do get notifications and it does work! I am using default security settings for IE so there should be no difference between my settings and theirs.
Could this be related to my user permissions vs theirs, or the fact that the files are read-only (because they are coming from source control and are also being made read-only when put on the shared drive.) or unknown dark Microsoft forces beyond human comprehension?
Thanks,
Josh
I believe you may want to create an HTA (HTML Application) instead of a web page. Writing HTA's gives you more privileges as far as ActiveX objects are concerned. Check out this page from Microsoft: http://msdn.microsoft.com/en-us/library/ms536496(v=vs.85).aspx.
To answer your question about privileges, I believe that some of your coworkers' IE settings probably prevent web pages from using ActiveX objects. Your settings may be such that you are prompted whenever ActiveX object are about to be created.

Using Toolbar to submit SAS code from Editor

When submitting SAS code via the SAS Toolbar (eg cmjohns response) the compiler knows that the code is being "DM'd" and will not run certain code (eg %window).
Is there a way to trick SAS into believing that code submitted from the Toolbar is coming from the Editor, therefore allowing interfaces (using %window) to be triggered via point and click?
It isn't super clean, but this will do it. The only downside is a program editor window will be open after it runs. There's probably a way to close it when it's done but I don't know what that is off hand.
pgm; clear;include "C:\path\code.sas"; submit;
Basically, this says to open a new program editor window and make sure no other code is in it, then include the contents of code.sas into the editor, then submit all the code that's in the program editor.
As a side note, in addition to a toolbar button, I think you could map a function key to a command like this as well. Press F9 to pull up the current mapping. There is a limit to the length of the command mapped to a key though so no long paths.

Resources