I have a simple outlook ribbon with an editBox. Once the user clicks the send button, I capture the string in the editBox and use it in the Application_ItemSend..
My problem is, after the function is done, I want to RESET the UI of the ribbon (just the editBox) so that the user won't have the previously typed string in the same box when opening up a new message screen. I tried the Ribbon.Invalidate but I can't seem to get rid of that string value. When I re-open the "New Email" screen, the old value is still there.
Here is the code:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load_2010">
<ribbon>
<tabs>
<tab idMso="TabNewMailMessage">
<group id="TaskManager" insertBeforeMso="GroupSend" label="Task Manager">
<editBox id="editboxTaskID" label="Task ID #: " onChange="editboxTaskID_OnChange"
imageMso="RecordsAddFromOutlook" sizeString="wwwwww"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
And the VB Code:
<Runtime.InteropServices.ComVisible(True)> _
Public Class CustomRibbon
Implements Office.IRibbonExtensibility
Private ribbon As Office.IRibbonUI
Public strTask_ID As String = ""
Public Sub New()
End Sub
Public Function GetCustomUI(ByVal ribbonID As String) As String Implements Office.IRibbonExtensibility.GetCustomUI
Return GetResourceText("Addin.Ribbon.xml")
End Function
Private Sub Application_ItemSend(ByVal Item As Object, ByRef Cancel As Boolean)
Me.ribbon.Invalidate()
Try
'SOME CODE HERE WHICH WORKS FINE!
Catch ex As Exception
End Try
End Sub
'Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1.
Public Sub Ribbon_Load_2010(ByVal ribbonUI As Office.IRibbonUI)
Me.ribbon = ribbonUI
AddHandler Globals.ThisAddIn.Application.ItemSend, AddressOf Application_ItemSend
End Sub
Public Sub editboxTaskID_OnChange(ByVal control As Office.IRibbonControl, ByVal Text As String)
strTask_ID = Text
End Sub
Public Sub AttachmentRibonClick(ByVal control As Microsoft.Office.Core.IRibbonControl)
Globals.ThisAddIn.TriggerTaskWindow("Attachment")
End Sub
Private Shared Function GetResourceText(ByVal resourceName As String) As String
Dim asm As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
Dim resourceNames() As String = asm.GetManifestResourceNames()
For i As Integer = 0 To resourceNames.Length - 1
If String.Compare(resourceName, resourceNames(i), StringComparison.OrdinalIgnoreCase) = 0 Then
Using resourceReader As IO.StreamReader = New IO.StreamReader(asm.GetManifestResourceStream(resourceNames(i)))
If resourceReader IsNot Nothing Then
Return resourceReader.ReadToEnd()
End If
End Using
End If
Next
Return Nothing
End Function
End Class
The invalidate method is used to signal that a control has been updated and needs to be re-rendered on the screen. It will not clear data from a control. What you need to do is set the property on the control (the edit box in this case) that stores the offending string value to an empty string.
Ok, I figured it out.
Apparently after you invalidate the controls, you need to use GetText function of the Editbox to init the value.
Public Function editboxTaskID_GetText(ByVal control As Office.IRibbonControl) As String
Return ""
End Function
I also noticed other sites use different signature for the function - which does not work. I believe Microsoft changed this from a Sub to a Function when moving to 2010 Interop.
I wish Microsoft had better documentation for this.
Happy programming!
Related
Im trying to get this code to work with buttons in visual basic. Ive looked on the internet and the only solutions I could find for volume controls are all written in C#. I converted this code to Visual Basic. Can someone overlook this code for me?
I was getting errors with me.handle
Imports System
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Namespace Test
Public Class Test
Private Const APPCOMMAND_VOLUME_MUTE As Integer = &H80000
Private Const APPCOMMAND_VOLUME_UP As Integer = &HA0000
Private Const APPCOMMAND_VOLUME_DOWN As Integer = &H90000
Private Const WM_APPCOMMAND As Integer = &H319
<DllImport("user32.dll")>
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Private Sub Mute()
SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, CType(APPCOMMAND_VOLUME_MUTE, IntPtr))
End Sub
Private Sub VolDown()
SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, CType(APPCOMMAND_VOLUME_DOWN, IntPtr))
End Sub
Private Sub VolUp()
SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, CType(APPCOMMAND_VOLUME_UP, IntPtr))
End Sub
End Class
End Namespace
In your code, Me.Handle is trying to reference a field or property called Handle on the same class (Test), but no such field or property exists.
You will need to find a way of obtaining the handle. The approach varies based on whether you are a WinForms or WPF application. If you are a console application, you will need to create a window (even if you don't show it) to participate in Windows Messages (i.e. the WM_* values you're using).
I have 1 web form and multiple user controls. One of the user controls fires an event. The page is listening and gets the value the control sends out. However the other user controls listening attach to the event but never get to the method.
User Control 1
public delegate void GetOrgIdEventHandler(long orgId);
public event GetOrgIdEventHandler GetOrgId;
protected void gvSearchResults_SelectedIndexChanged(object sender, EventArgs e)
{
if (GetOrgId != null)
{
GetOrgId(Id);
}
}
Web Form
//Search1 is the Id of the User Control on the web form - This is working.
//It calls the method in the assignment
Search1.GetOrgId +=
new SearchGridViewSelectedIndexChangedEventHandler(GetTheOrgId);
User Control 2
//SearchUserControl is the name of the User Control 2 Class
protected SearchUserControl mySuc = new SearchUserControl();
//The line below works, however the method does not get called. This is where it fails.
//I set a breakpoint in GetTheOrgId but I never get to that break.
mySuc.GetOrgId += new SearchGridViewSelectedIndexChangedEventHandler(GetTheOrgId);
Yes, you can raise events in the first control, have it picked up in the parent, and then have the parent call a method/function in the second control. Example (in VB.Net):
User control one:
Partial Class user_controls_myControl
Inherits System.Web.UI.UserControl
Public Event DataChange As EventHandler
'now raise the event somewhere, for instance when the page loads:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RaiseEvent DataChange(Me, New EventArgs)
end sub
end Class
This will raise an event, called DataChange, when the control loads. Or, you can raise it in response to another event withing the controls (like if a button gets pushed). This will raise an event that the parent can subscibe to, like this (assuming you have a control on the page called MyControl1):
Main Page:
Protected Sub myControl_dataChange(ByVal sender As Object, ByVal e As EventArgs) handles myControl1.DataChange
End Sub
Now, you can then expose a method in your second control, like this:
Partial Class user_controls_myOtherControl
Inherits System.Web.UI.UserControl
public sub callMe()
'do something
end Sub
end Class
You can then call the method in the second control, from the parent page, like this:
me.userConrol2.callMe()
If you still have questions, let me know.
Im trying to create a windows service with vb.net but when I run:
InstallUtil.exe myservice.exe
I'm getting the following error in the MyService.InstallLog file:
Restoring event log to previous state for source DebtorInvoiceMailingService.
An exception occurred during the Rollback phase of the System.Diagnostics.EventLogInstaller installer.
System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.
An exception occurred during the Rollback phase of the installation. This exception will be ignored and the rollback will continue. However, the machine might not fully
DebtorInvoiceMailingService.vb
Imports System.ServiceProcess
Imports System.Timers
Public Class DebtorInvoiceMailingService
Inherits ServiceBase
Private _timer As Timer
Private _lastRun As DateTime = DateTime.Now
Private _notificationsManager As Notifications
Public Sub New()
Me.ServiceName = "DebtorInvoiceMailingService"
End Sub
'When service starts
Protected Overrides Sub OnStart(ByVal args() As String)
MyBase.OnStart(args)
'This object will do what im looking for (monitore a folder)
Me._notificationsManager = New Notifications
Me._timer = New Timer
'Service will be executed every 24 hours
Me._timer.Interval = 1000 * 60 * 60 * 24
Me._timer.Enabled = True
'Service will execute timer_Elapsed()
AddHandler Me._timer.Elapsed, AddressOf timer_Elapsed
End Sub
'When service stops
Protected Overrides Sub OnStop()
MyBase.OnStop()
Me._timer.Dispose()
End Sub
'Function executed every 24 hours
Private Sub timer_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)
If (Me._lastRun.Date > DateTime.Now.Date) Then
Me._timer.Stop()
'You have to stop your timer because if the task that you
'are about to perform takes longer than the timer.interval
'the task will be executed multiple times
Me._notificationsManager.execute() 'this function will send an email
Me._lastRun = DateTime.Now
Me._timer.Start()
End If
End Sub
Shared Sub Main()
ServiceBase.Run(New DebtorInvoiceMailingService)
End Sub
End Class
ProjectInstaller.vb
Imports System
Imports System.ServiceProcess
Imports System.ComponentModel
Imports System.Configuration.Install
<RunInstallerAttribute(True)> _
Public Class ProjectInstaller
Inherits System.Configuration.Install.Installer
Public WithEvents ServiceProcessInstaller1 As ServiceProcessInstaller
Public WithEvents ServiceInstaller1 As ServiceInstaller
Public Sub New()
MyBase.New()
Me.ServiceProcessInstaller1 = New ServiceProcessInstaller()
Me.ServiceInstaller1 = New ServiceInstaller()
'ServiceProcessInstaller1
Me.ServiceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
'ServiceInstaller1
Me.ServiceInstaller1.Description = "Auto mailing invoices to debtors every 24 hours."
Me.ServiceInstaller1.DisplayName = "DebtorInvoiceMailingService"
Me.ServiceInstaller1.ServiceName = "DebtorInvoiceMailingService"
Me.ServiceInstaller1.StartType = ServiceStartMode.Manual
'ProjectInstaller
Me.Installers.Add(Me.ServiceProcessInstaller1)
Me.Installers.Add(Me.ServiceInstaller1)
End Sub
Please Can someone help me? Thanks :)
Be sure to run the InstallUtil from a command windows launched "As Administrator".
I'm seeing some weird behaviour debugging my C# code - I cant post my exact code but essentially I have a partial abstract base class that defines an Execute method:
public abstract partial class MyBase
{
public abstract void Execute();
protect static object SomeMethod()
{
object aaa = OtherClass.GetObject();
// etc...
}
}
I then have another partial class which implements this method, and calls some static methods on the base class:
partial abstract class MyParent : MyBase
{
public void Execute()
{
object myobj = SomeMethod();
// etc...
}
}
Both of these partial classes have are extensions of partial classes generated using xsd.exe from a schema.
What I'm seeing is that if I attempt to step-into my implementation of Execute(), the Visual Stuido debugger jumps through these methods - for example in this case it would step straight through to the OtherClass.GetObject() method. The call stack still shows all the frames inbetween Execute() and OtherClass.GetObject(), and even lets me set them to be the active frame, however I can't do a line-by-line step through the code unless I place a breakpoint on each and every line.
Why is this?
How can I fix it so I can debug normally again!?
xsd.exe typically decorates generated classes with the DebuggerStepThrough attribute, which means the debugger will .. well, you get the picture.
I've dealt with this in the past with a simple .vbs script that I call after invoking xsd.exe (typically as part of a pre-build step):
Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(WScript.Arguments(0), ForReading)
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText,
"[System.Diagnostics.DebuggerStepThroughAttribute()]", "")
Set objFile = objFSO.OpenTextFile(WScript.Arguments(0), ForWriting)
objFile.WriteLine strNewText
objFile.Close
You call it with the name of the generated file as a parameter, as in:
wscript.exe remove_attribute.vbs XsdGeneratedClasses.cs
Also, make sure the Just My Code checkbox is unchechedk, just in case.
Every time I view a form or dialog in Visual Studio (2005) the Properties and Toolbox panes show up on the right side of my screen. That's good to have because they are useful for manipulating dialogs.
However once I switch back to source code these panes just get in the way... is there a way to get them to go away automatically?
I've done something recently in VS2010 using a macro that shows and hides the Tools panel when switching back and forth from code to design view in asp.net MVC3 views. It could be easily adapted to do the same for your situation I think.
This goes in the EnvironmentEvents class file in in the VS Macro IDE after the pre-generated content.
<System.ContextStaticAttribute()> Public WithEvents CommandEvents As EnvDTE.CommandEvents
Public Sub DTEEvents_OnMacrosRuntimeReset() Handles _
DTEEvents.OnMacrosRuntimeReset
CommandEvents = DTE.Events.CommandEvents
End Sub
Private Sub DTEEvents_OnStartupComplete() Handles _
DTEEvents.OnStartupComplete
CommandEvents = DTE.Events.CommandEvents
End Sub
Public Sub CommandEvents_AfterExecute( _
ByVal Guid As String, _
ByVal ID As Integer, _
ByVal CustomIn As Object, _
ByVal CustomOut As Object) _
Handles CommandEvents.AfterExecute
If DTE.Commands.Item(Guid, ID).Name = "View.ViewDesigner" Then
DTE.ExecuteCommand("View.Toolbox")
End If
If DTE.Commands.Item(Guid, ID).Name = "View.ViewMarkup" Then
DTE.Windows.Item(Constants.vsWindowKindToolbox).Close()
End If
End Sub
It could probably be better optimized using the guids of the event rather than the if statements. It works when you use the hot keys for switching views as well as the view menu, but not the context menu.
for vs2015:
Menu > Tools > Extensions and Updates
install "Visual Commander". (Now you have New Menu called "VCmd")
Menu > "VCmd" > Extensions ... (You will see an Extensions Pane At Right)
Press Add Button at the Extensions Pane. (New tab Wİndow will open.)
write a name for extention.
select language as C#.
paste the code below:
Press Save. Then Press Compile. Then Press Install
using EnvDTE;
using EnvDTE80;
public class E : VisualCommanderExt.IExtension
{
private EnvDTE80.DTE2 DTE;
private EnvDTE.WindowEvents windowEvents;
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) {
this.DTE = DTE;
DTE.Events.WindowEvents.WindowActivated += OnWindowActivated;
}
public void Close() {
// i read somewhere this has to be done on close.
// but it gives gives me error on every IDE close. so i commented it .
//DTE.Events.WindowEvents.WindowActivated -= OnWindowActivated;
}
private void OnWindowActivated(Window gotFocus, Window lostFocus) {
HidePropertiesWindowInCodeOrTextView(gotFocus );
}
public void HidePropertiesWindowInCodeOrTextView(Window gotFocus ) {
if (gotFocus.Document == null) return;
var pwin = DTE.Windows.Item(Constants.vsWindowKindProperties);
pwin.AutoHides = !gotFocus.Caption.EndsWith(" [Design]") ;
}
}
Rather than give up the space on the right side of the screen, I dragged my properties and toolbox panes over to the left-side frame that hosts the solution explorer and class view, etc. I'd rather have one multi-purpose box on one side of the screen than to have the code surrounded. If you need them both, you can put the toolbox in the solution explorer pane, then stack the properties pane beneath the solution explorer, which keeps a few properties in view at all times along with the toolbox.
I know it's not quite the answer you were looking for, but it's a different way of keeping that screen real estate available for code without messing with auto-hide (I find auto-hide to be really an annoyance more than a help.)
For vs2019:
I improve bh_earth0's solution. Now it saves visibility states of Properties and ToolBox when you jump to code. And when design tab is activated it loads previous state of panes.
Menu > Extensions > Manage Extensions
Find and install "Visual Commander". (Now you have New Menu called "VCmd")
Menu > "VCmd" > Extensions ... (You will see an Extensions Pane At Right)
Press Add Button at the Extensions Pane. (New tab Wİndow will open.)
write a name for extention (e.g. AutoHide).
select language as C#.
copy and paste the code below:
Press Save. Then Press Compile. Then Press Install
Restart the Visual Studio and enjoy :-)
using EnvDTE;
using EnvDTE80;
public class E : VisualCommanderExt.IExtension
{
private EnvDTE80.DTE2 DTE;
private EnvDTE.WindowEvents windowEvents;
private bool bPropWinVisible = false;
private bool bToolWinVisible = false;
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) {
this.DTE = DTE;
DTE.Events.WindowEvents.WindowActivated += OnWindowActivated;
}
public void Close() {
}
private void OnWindowActivated(Window gotFocus, Window lostFocus) {
if (gotFocus.Document == null) return;
if (lostFocus.Document == null) return;
var pwin = DTE.Windows.Item(Constants.vsWindowKindProperties);
var twin = DTE.Windows.Item(Constants.vsWindowKindToolbox);
if(gotFocus.Caption.EndsWith(".cs [Design]") && lostFocus.Caption.EndsWith(".cs") ) {
pwin.AutoHides = bPropWinVisible;
twin.AutoHides = bToolWinVisible;
}
else if(gotFocus.Caption.EndsWith(".cs") && lostFocus.Caption.EndsWith(".cs [Design]")) {
bPropWinVisible = pwin.AutoHides;
bToolWinVisible = twin.AutoHides;
pwin.AutoHides = true;
twin.AutoHides = true;
}
}
}
If you click the 'pin' icon on those tool windows, you can toggle whether the windows stay open all the time, or only when the mouse is near them. Of course, sometimes my mouse strays over in that direction and they pop out when I don't want them to, but such is life...