I think the title or the question is clear enough. I saw something about the EventSink, but I found it difficult to use. Any hint?
The Visio Primary Interop Assembly exposes these events as C# events therefore you can simply hook the event with a delegate.
See this simple example:
namespace VisioEventsExample
{
using System;
using Microsoft.Office.Interop.Visio;
class Program
{
public static void Main(string[] args)
{
Application app = new Application();
Document doc = app.Documents.Add("");
Page page = doc.Pages[1];
// Setup event handles for the events you are intrested in.
// Shape deleted is easy.
page.BeforeShapeDelete +=
new EPage_BeforeShapeDeleteEventHandler(onBeforeShapeDelete);
// To find out if a shape has moved hook the cell changed event
// and then check to see if PinX or PinY changed.
page.CellChanged +=
new EPage_CellChangedEventHandler(onCellChanged);
// In C# 4 for you can simply do this:
//
// page.BeforeShapeDelete += onBeforeShapeDelete;
// page.CellChanged += onCellChanged;
// Now wait for the events.
Console.WriteLine("Wait for events. Press any key to stop.");
Console.ReadKey();
}
// This will be called when a shape sheet cell for a
// shape on the page is changed. To know if the shape
// was moved see of the pin was changed. This will
// fire twice if the shape is moved horizontally and
// vertically.
private static void onCellChanged(Cell cell)
{
if (cell.Name == "PinX" || cell.Name == "PinY")
{
Console.WriteLine(
string.Format("Shape {0} moved", cell.Shape.Name));
}
}
// This will be called when a shape is deleted from the page.
private static void onBeforeShapeDelete(Shape shape)
{
Console.WriteLine(string.Format("Shape deleted {0}", shape.Name));
}
}
}
If you haven't already downloaded the Visio SDK you should do so. Recent versions of the SDK it contains many useful examples include one called "Shape Add\Delete Event". If you have the 2010 version can browse the examples by going to Start Menu\Programs\Microsoft Office 2010 Developer Resources\Microsoft Visio 2010 SDK\Microsoft Visio Code Samples Library.
I believe that you have to implement EvenSink to get access to "ShapesDeleted", i.e.
(short)Microsoft.Office.Interop.Visio.VisEventCodes.visEvtCodeShapeDelete
the code above will help you if you are looking for the event "BeforeShapeDelete" not the "after"ShapeDelete ;)
Related
A while ago I wrote some cool vision stuff in c++. Later I found out my code needs to be added into an existing executable that is written in c#. Therefor, I want to write the same vision algorithmes in c# in such a way that my code can be run as an executable.
I have downloaded Emgu 3.3 and I use OpenCV 3.4 and Visual Studio 2017. C# is new for me. I did the tutorial where you make your form, give it some buttons and assign functions to the buttons. That all worked fine.
Then I started to look for ways on how to import a videofeed from my webcam into my form. So I just want to get a live feed from my webcam in my form. After 3 days of frustration I have gotten totally confused with all the references. Which one do I need which one do I not need. Every code that I find and try to implement as a start seems to give a different issue. And all I want is just one clean screen with my camera feed.
So sorry for this super long story, but can someone please help me.
I know I need to create a picturebox. I just want to obtain a VideoCapture from my webcam and send this directly to the picturebox. As as start of course. From there on I can continue figuring stuff out but I need the base.
From there on I would like to perform imageprocessing on the videofeed and display another picturebox with the edited videofeed. But that's all for later!
I hope my question isn't too vague since I also do not supply some code..
Thank you
A example of showing your Webcam in WinForm using VideoCapture of Emgu 3.3 is as below:
public partial class Form1 : Form
{
VideoCapture _capture;
private Mat _frame;
private void ProcessFrame(object sender, EventArgs e)
{
if (_capture != null && _capture.Ptr != IntPtr.Zero)
{
_capture.Retrieve(_frame, 0);
pictureBox1.Image = _frame.Bitmap;
}
}
public Form1()
{
InitializeComponent();
_capture = new VideoCapture(0);
_capture.ImageGrabbed += ProcessFrame;
_frame = new Mat();
if (_capture != null)
{
try
{
_capture.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
I cannot seem to find a good solution for this issue online. I have a device that is running Windows Embedded Handheld 6.5. I run the solution located at below
C:\Program Files (x86)\Windows Mobile 6.5.3 DTK\Samples\PocketPC\CS\GPS
I deploy the code to my device, not an emulator, and the code breaks with a null reference exception at
Invoke(updateDataHandler);
The solution ive seen recommends changing this to below
BeginInvoke(updateDataHandler);
But now the code breaks at Main with NullRefreceException.
Application.Run(new Form1());
Has anyone found a solution for this?
Did you alter the code? updateDataHandler is initialized in Form_Load:
private void Form1_Load(object sender, System.EventArgs e)
{
updateDataHandler = new EventHandler(UpdateData);
so that object will not be NULL. But there are other annoyances with the code, especially the Samples.Location class. You may instead use http://www.hjgode.de/wp/2010/06/11/enhanced-gps-sample-update/ as a starting point and the older one: http://www.hjgode.de/wp/2009/05/12/enhanced-gps-sampe/
The main issue with the sample is that it does not use a callback (delegate) to update the UI. If an event handler is fired from a background thread, the handler can not directly update the UI. Here is what I always use to update the UI from a handler:
delegate void SetTextCallback(string text);
public void addLog(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.txtLog.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(addLog);
this.Invoke(d, new object[] { text });
}
else
{
txtLog.Text += text + "\r\n";
}
}
Initial Situation:
We are developing an Add-in for Outlook 2010 in C# with VS.NET 2010 based on Framework 4.0, VSTO, DevExpress WinForm Controls. In Designer we have a Ribbon with a RibbonTab, then a RibbonGroup then a RibbonButton. We're consuming WebServices from within this Outlook Add-in.
Objective:
We need to enable/disable the RibbonButtons when the WebService is available/unavailable (from/out of the code)
we've found the following links:
Links
Ribbon Object Model Overview: http://msdn.microsoft.com/en-us/library/bb608623.aspx
Ribbon Overview: http://msdn.microsoft.com/en-us/library/bb386097.aspx
Walkthrough: Updating the Controls on a Ribbon at Run Time: http://msdn.microsoft.com/en-us/library/bb608628.aspx
After hours of trying to figure out how to implement this we deciced to post/ask this question here on SO. Does anybody have a sample code? We tried the IRibbonExtensibility and CreateRibbonExtensibilityObject => we added the RibbonTab, Group and Button and added a subscription to the Click Event => The Event is fired but not handled (in button_Click(...) => System.Diagnostics.Debugger.Break() is not breaking the code execution)
Thanks!
Christian
You'll want to invalidate the Ribbon at a fairly frequent rate in order to refresh the visibility of each tab/button. You can do this by subscribing to the Click event (as you've done) and then calling RibbonObject.Invalidate();. Then add a getEnabled="yourTestFunction" parameter to each button, with public bool yourTestFunction(Office.IRibbonControl control) (Defined in the Ribbon.cs file) returning whether the web service is available or not.
Keep in mind if the web service is down, each click could hang your application for the amount of time you set on your timeout in the web service check
Edit:
Just realized the _Click event isn't mapped in the Excel COM library, so here's a bit of code that will run each time the cell selection is changed (not as frequent as every click, but hopefully good enough).
ThisAddIn.cs:
public static Excel.Application e_application;
public static Office.IRibbonUI e_ribbon;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
e_application = this.Application;
e_application.SheetSelectionChange += new Excel.AppEvents_SheetSelectionChangeEventHandler(e_application_SheetSelectionChange);
}
void e_application_SheetSelectionChange(object Sh, Excel.Range Target)
{
e_ribbon.Invalidate();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
e_application.SheetSelectionChange -= new Excel.AppEvents_SheetSelectionChangeEventHandler(e_application_SheetSelectionChange);
e_application = null;
}
Ribbon1.cs:
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
ThisAddIn.e_ribbon = ribbonUI; //Add this line
}
and
public bool getEnabledTest(Office.IRibbonControl control)
{
//Whatever you use to test your Web Service
//return false;
}
Ribbon1.xml:
<button id="WebService" label="Use The Web Service" onAction="executeWebService" getEnabled="getEnabledTest" />
The following article titled Adding Custom Dynamic Menus to the Office Fluent User Interface will point you in the right direction.
The below is an example of a dynamically created menu, you can modify the tutorial to fit your particular need.
ok, thanks for the tips. Finally i solved it like this:
i declared a static ribbon object like:
public static RibbonIet ribbon {get; set; }
in the load event of the Ribbon i assign the Ribbon (this) like:
Session.Common.ribbon = this;
now i can control the RibbonButton like:
Session.Common.ribbon.buttonCreateIncident.Enabled = true;
Since the webService call is running in a seperate thread, i had to use a MethodInvoker to change enable/disable the buttons. it goes like this:
If (InvokeRequired)
{
Invoke(new MethodInvoker(() => Session.Common.ribbon.buttonCreateIncident.Enabled = true));
}
maybe this is of help for someone else.
I have a project which contains multiple forms that have a microsoft visio activex control in them.
For some reason they keep interfering with one another. Here's a snip it of my code, simplified:
private void OpenRDM()
{
if (RDMform == null)
{
// Constructor opens a new form, and populates a Visio control on it
RDMform = new RDM.MainForm();
}
RDMform.Show();
}
private void OpenPSM()
{
if (PSMform == null)
{
// Constructor opens a new form, and populates a Visio control on it
PSMform = new PSM.MainForm();
}
PSMform.Show(); // Problem occurs here, PSM Visio control gains contents of RDM's Visio Control
}
public void main()
{
OpenRDM();
RDMform.Hide();
OpenPSM();
PSMForm.Hide();
}
I can call one of these functions and it works fine, but if I hide the form, and then call the other one, its Visio control loads with the contents of the first form, instead of the correct new stuff. I traced it, and the second Visio control is populated just fine, until the second Show() method is called, at which point it mysteriously goes back to the contents of the first Visio control.
I can't figure out what is going on here, Visio seems to think that they are the same control.
Edit*
In response to comment about setting the .src property. The source is a behemoth, so I can't reasonably post everything it does. But here's those lines.
in RDM:
If visioControl.Src <> TemplateFullName Then
visioControl.Src = TemplateFullName
Else
visioControl.Src = ""
visioControl.Src = TemplateFullName
End If
in PSM:
drawingControl.Src = string.Empty;
drawingControl.Src = vstFilepath;
InitializeFlowDiagram(dbFilepath); // updates shapes from database values
Both modules actually use the same visio diagram including page names, they just display it in different ways. So I'd like to be able to back and forth between them without having to reload everything. Maybe the activeWindow is involved in the problem, I'll have to do more research.
I'm considering migration of all of our Word templates from VBA to VSTO and have the following question: How can I debug code in a VSTO project?
Unlike debugging in VBA, I can't see the results of code executing line-by-line when stepping through a procedure.
For example, I build a prototype Word document in VS 2019:
using ...;
namespace MyCompany.OfficeTemplates.MyTemplate
{
public partial class ThisDocument
{
private void ThisDocument_Startup(object sender, System.EventArgs e)
{
}
private void ThisDocument_Shutdown(object sender, System.EventArgs e)
{
}
private void ThisDocument_New()
{
var currentSelection = Application.Selection;
currentSelection.TypeText("This text was added by using code.");
}
#region VSTO Designer generated code
/// ...<summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisDocument_Startup);
this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
this.New += new Microsoft.Office.Interop.Word.DocumentEvents2_NewEventHandler(this.ThisDocument_New);
}
#endregion
}
}
I plan to put way more code (showing a dialog box, choosing customers, choosing language and other information) into the ThisDocument_New() event. Why is the text not inserted into the word document when I step over the command ...TypeText()... with the debugger?!?
Instead, It's inserted when debugger leaves ThisDocument_New()?
What am I missing and where else to put my code when ThisDocument_New() does not allow propper debugging?
That one cannot see what's happening during code execution is typical for VSTO. Debugging is different than with VBA - the results are only visible after the code has finished. Nothing can be done to change this - it's in the nature of the thing (.NET <-> COM interaction).
I struggled with this, myself, when starting with VSTO, and had to learn to work around it.
Generally, if during trouble-shooting it's necessary to see what's happening as it happens, I first test in VBA, then transfer that code to VSTO.
If it's necessary to check values being generated by code as it runs I stick some Debug.Print lines in that I can follow in the Visual Studio output window when stepping through the code.
It's also possible to track what's assigned to objects when stepping through the code.