Making a MS Word document "absolutely" read only - vba

Is it possible in vba to make a document read only and in such a way as to prevent any user from making any changes to it?
The protect method for the document object allows you to make a document read only, but as soon as the user tries to edit the document it provides access to the Restrict Editing Pane which gives the user access a "Stop Protection" button.
I would like to prevent the Restrict Editing Pane from appearing.

Whilst it doesn't seem possible to stop the "Restrict Editing" panel from opening. It is possible to prevent the user from enable editing by adding a mouse hook and catching any mouse clicks within the Restrict Editing panel. Code in Delphi is
Hdl := WindowFromPoint (Mouse.CursorPos);
GetClassName (Hdl, clsName, 256);
GetWindowText (Hdl, wText, 256);
if (uppercase(clsName) = 'BOSA_SDM_MSWORD')
and (uppercase(wText)= 'PROTECT DOCUMENT') then {do whatever}
This catches any clicking within Restrict Editing panel and is not pinpointedto the "Stop Protection" button. I would assume it would be possible to drill down further to identify the button specifically, but it seems to me unnecessary to do so. Also, if the class name or window text changes then the function will fail.
Aside from being clunky and potentially not future proof, it does however work.

Related

VBA: How would my code check whether I have unlocked it?

Is there a way for my code to check whether the code in the VBA editor was unlocked for editing? I want to create a global "admin mode" variable which would give me more control in a dev vs. a live environment.
This will do the trick, and should work as a UDF (though it will be volatile). However, this requires that macros have programmatic access to VBProject, which is NOT enabled by default and must be enabled (PER USER) in the Trust Center options in Excel. Chick and egg, there's no way to programmatically set that trust center option.
Public Function IsDevMode() As Boolean
IsDevMode = (ThisWorkbook.VBProject.Protection=0)
End Function
However, there's no event to trap to know when this value changes, so it will be difficult to use it to make the changes to your workbook to move in and out of "developer mode." A better option might be to add a button somewhere that toggles "developer mode" (hiding and showing things, unlocking/locking sheets, etc.), and in that toggle button's click method, use the code above to see if the code has been unlocked in this session. If so, proceed, and if not, ignore. That way, by unlocking your code, you basically grant yourself access to use said button.

Do not require attention for ShowDialog

I had a question about Dialogs in VB.NET. I am working on a point of sale program, and at one point during a sale, I have a few windows that pop up. For example, a user will go into a sale that is window A. In window A, they have the option of entering products, etc., and if they choose a 'repair' product, it opens window B, allowing them to choose options. In window B, there is a button that pops up window C that allows them to attach products TO the repair. My issue is with window B opening window C.
Because I open window B as a Dialog (in order to check if DialogResult.OK is true), any window I open with B is non-touchable, as B is a Dialog and requires attention before going to any other windows/forms.
My question is - is there any way to still use a dialog, but allow for manipulating other open forms while the dialog is up, and if not, what would be the best way to check if the user selected OK, or cancelled out of the window?
The only solution I can think of right now would be to open window C as a dialogue as well (it's actually a UserControl, and I'm still trying to find where in the code it's actually getting openned/called), or to create a variable that is passed in to the form, and then passed back out when it's closed, that basically sets a flag to either continue or cancel...
Any advice/ideas??
If I were to explain this using code, this answer would be very long, so instead I'm going to give you a high level overview.
.Show() vs .ShowDialog()
The link below will take you off to Microsofts website to explain the technical differences between these two. However in laymans terms, .ShowDialog() will create the form where it is the only window allowed to have focus in the application. Forms that are called in this instance are hierarchical, in that if you open them in order of 1,2,4,3 then they must be closed in the 3,4,2,1 order. Forms that are opened with just .Show() can be focused at any time.
How to: Display Modal and Modeless Windows Forms
Form.FormBorderStyle property
This property controls how the OS will display the window. The different options under this selection changes the way the window behaves. Depending on the options that are chosen you can make a window that only has a close button on it, or it may not even have a title bar at all. Setting this option to None will take away all controls of the form and only leave you with the Me.ClientArea to work with. When you want a completely custom GUI, this is how you do it but you have to implement your own controls for everything, closing the form, size handles, the ability to move the form on the screen, etc...
Form.FormBorderStyle Property
Passing data between forms
When someone asks how to pass data back and forth between forms, they are usually talking about modeless forms that were created using .Show(). The most common thing I see on SO is to use the tag property of an object (a form is an object that has this property too) to pass data back and forth. While I won't say this is a bad practice, I will recommend creating public properties on your forms. These can be set from a separate form and you can perform additional actions when setting the values (be careful though, this way of doing things isn't thread safe). If you are using a Modeless form as though it were a Modal form, then you can simply override the .Dispose property to return a value or you can create a method named DialogResult that will return the value you need. The caveat to using a DialogResult or similar method is that if the form has been disposed then you can't access the value you wanted to return.
You can use myNewForm.Show(Me) for the Window you want to be shown as a dialog. This will show myNewForm as a child of the current form, but lets you interact with the current form.

CTRL+ TAB when webbrowser is in focus

I have a windows application with a tabcontrol. One of the tab of the tabcontrol has a webbrowser control.Now the issue that I am facing is when the focus is inside the webbrowser control, the normal Ctrl+Tab functionality of the tabcontrol is not working.I want the Ctrl+Tab to change the selected tab of tabcontrol even when the focus is inside webbrowser control in selected tab.How to achieve this ?
I have already tries overriding ProcessCmdKey.but it does not get hit when focus is inside webbrowser control.
I also tried registerhotkey method ,it works but it locks the Ctrl+Tab hotkey within my application & system doesn't respond to any other Ctrl+Tab presses outside my application when application is running, which is expected behaviour of registerhotkey.
Here is the code you need:
If WB.ContainsFocus Then
MsgBox("We have focus, disappearing...")
WB.Document.Body.RemoveFocus()
End If
Now, the question is, when to run that code. If you put it in the WebBrowser1_GotFocus event, you'll need to turn it on and off. Turn the code off if the user is interacting with the WB Control, and turn it back on when they are not and when you expect to be experiencing the problem you've mentioned.
Of course, you could add another line to ensure a particular control/tab/panel etc gets focus after you remove focus from the body. Also, here are 3 other SO questions that have answers which may help you, but these will take you in directions different to the direction I've provided, probably due to the fact that the questions are not identical to yours, but are similar enough to be useful (not listed in order of preference).
Prevent WebBrowser control from stealing focus?
Webbrowser steals focus
Focusing WebBrowser control in a C# application
UPDATE:
I just wanted to add, instead of the .Body.RemoveFocus() you could do this:
WB.Document.Body.Parent.RemoveFocus()
Which I prefer, since the .Document object didn't have an explicit .RemoveFocus method on the intellisense I was gettign in VS2012 RC. This is probably referring to the HTML tag (and not the .Document object) and since the html tag is the only parent to the body tag, it makes sense, and there is no "HTML" object directly available in the intellisense under object, since you can get it via other means, so it's just more convenient doing it this way.
Cheers, and let me know if you need more info on anything.

Is it possible to have an extension library dialog box within a repeat control?

I'm running with an 8.5.3 UP1 server and I have a need to have many dialog boxes (for confirmation purposes) for a whole bunch of "action buttons" on an xpage. The code for these dialog boxes is almost exactly the same with the exception of the confirmation message being different and the client-side JS function they are calling if the Yes button is selected.
Since I really hate repeating code over and over, I was wondering if it is at all possible to put a xe:dialog control within a repeat control and specify the message and function call from an array of values? I know I can't compute the ID of the dialog control and without that I'm not sure how I would reference the dialog to open and close it.
Any ideas? Thanks
Yes, this is possible.
Make sure that you specify that the dialog box's property for keepComponents is set to False. You don;t have to do anything special for opening or closing the dialog box, just use whatever ID you give the dialog box in you client-side action to open the dialog box in the repeat such as XSP.openDialog('#{id:myDialog}')
The XPages renderer will automatically calculate the correct ID names for you.

How to force user to deal with the Security Warning when starting Access 2007?

When a user start an Access 2007 database that have macros and vba, a security warning is shown. I want the user to deal with this warning, so if the the content is't enabled, the user should not be able to use the database.
Now I use a macro named AutoExec (opens a form that works like a menu), and that macro is run before the user deal with the security warning. But I want to check if the content is enabled and if not I will show a form that inform the user that they should enable the content.
So what I'm actually asking for is how do I do this:
If vba and macros is not enabled -> show form "information"
If vba and macros is enabled -> show form "start menu"
Ok, after a while I have the solution. Thanks for the answers who led me the right way.
This article from Microsoft is very helpful.
In the AutoExec-macro, I have two lines:
Line one: Conditions: [CurrentProject].[IsTrusted]=False and then I choose witch Form I want to open and in this case it is the "info about security warning form"
Line two: Conditions: [CurrentProject].[IsTrusted]=True and now open the "start menu form"
And that's all!
If the content is disabled, then you cannot check, since your code cannot run....
You might like to consider a start-up form ("information"). This will show without macros.
In addition, you can run some start-up code or a macro that closes the information form and opens the main form ("start menu"), if macros are disallowed, this will not run. However, I think you may get an unsightly warning.
EDIT
Set the timer interval to say, 100 and add a little code to Information form:
Private Sub Form_Timer()
DoCmd.Close acForm, "Information"
DoCmd.OpenForm "start menu"
End Sub
Just to add my solution -- I was just dealing with this issue.
By default, in database options have it set to open with form "notEnabled"
On this "not enabled" form, have some text, pictures, or what have you that lets the user know that he/she needs to 'enable content'.
In the on load event for this form, just put some VBA to open the actual form you want the user to be presented and close the "notEnabled" form.
This way, if the user opens the database without making it trusted, enabling content, they are stuck on the form that tells them how to do that. As SOON as it's trusted, the on-load event of the form will fire and redirect the user to whichever form you want, with content enabled.
If the user opens the database and already has trusted the file, they don't see the form telling them to make it trusted.
You can avoid this by setting the IsTrusted flag to TRUE in your AutoExec macro. See Transitioning Your Existing Access Applications to Access 2007 -- search for IsTrusted to get you to the heart of the explanation of how to handle it.
I don't know why people give suggestions that have not been tested yet. My solution is simple:
If: [CurrentProject].[IsTrusted]=False
RunMenuCommand: CloseDatabase
Else
If: [CurrentProject].[IsTrusted]=True
RunCode: (you run the code or macro you wanted to in the first place here)
This basically closes the database if the security warnings are coming on. If they are not, it opens just fine. The user that is the admin will need to decrease the macro security levels on the computer of whoever wants to access the database. This macro unlike others will actually run because it agrees with what Access wants.
You're Welcome!