Add OnClick Action to Shape Objects in MS PowerPoint - c#

I Have a requirement to add a OnClick action to Shape object in Micro Soft Power Point Addin for Office 2010 and above which is built using C# language. There are events like
SlideSelectionChanged
WindowBeforeRightClick
Which doesn't work as needed, Right Click Event doesn't even work on the Shape Objects.
Is there a way to subscribe to such type of events, I would not prefer to use MACRO however if that is inevitable I will use it.

This solution would work.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.WindowSelectionChange += OnWindowSelectionChanged;
}
void OnWindowSelectionChanged(PowerPoint.Selection Sel)
{
if (Sel.Type == PowerPoint.PpSelectionType.ppSelectionShapes)
{
PowerPoint.ShapeRange shapeRange = Sel.ShapeRange;
//Do some work
}
}
private void ThisAddIn_ShutDown(object sender, System.EventArgs e)
{
this.Application.WindowSelectionChange -= OnWindowSelectionChanged;
}
It's Good to have some flag to make sure you are doing the needful only on desired Shape Objects by setting some flag by using AltText like
if (Sel.ShapeRange.AlternativeText.Contains("SomeFlag"))
{
//Do some thing
}

Related

c# Detect mouse clicks anywhere (Inside and Outside the Form)

Is this possible to detect a mouse click (Left/Right) anywhere (Inside and Outside the Form) in an if statement? And if it's possible, how?
if(MouseButtons.LeftButton == MouseButtonState.Pressed){
...
}
Here is a starter, if I understood your needs of "clicking from outside the window" and Hans Passant's suggestion doesn't fit your needs. You might need to add an event handler for Form1_Click.
CAUTION: This code is provided to illustrate the concept. The threading synchronization in this sample is not 100% correct. Check the history of this answer for an attempt at a more "threading correct" one that sometimes throws exceptions. As an alternative, to get rid of all threading issues, you could have the task in StartWaitingForClickFromOutside be instead always running (aka be always in "listen" mode) as opposed to trying to detect the "within the form" or "outside the form" states and starting/stopping the loop accordingly.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseLeave += Form1_MouseLeave;
this.Leave += Form1_Leave;
this.Deactivate += Form1_Deactivate;
this.MouseEnter += Form1_MouseEnter;
this.Activated += Form1_Activated;
this.Enter += Form1_Enter;
this.VisibleChanged += Form1_VisibleChanged;
}
private AutoResetEvent are = new AutoResetEvent(false);
// You could create just one handler, but this is to show what you need to link to
private void Form1_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void StartWaitingForClickFromOutside()
{
are.Reset();
var ctx = new SynchronizationContext();
var task = Task.Run(() =>
{
while (true)
{
if (are.WaitOne(1)) break;
if (MouseButtons == MouseButtons.Left)
{
ctx.Send(CLickFromOutside, null);
// You might need to put in a delay here and not break depending on what you want to accomplish
break;
}
}
});
}
private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
private void Form1_MouseEnter(object sender, EventArgs e) => are.Set();
private void Form1_Activated(object sender, EventArgs e) => are.Set();
private void Form1_Enter(object sender, EventArgs e) => are.Set();
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (Visible) are.Set();
else StartWaitingForClickFromOutside();
}
}
}
If I understood you incorrectly, you might find this useful: Pass click event of child control to the parent control
When user clicks outside the form control, it losses the focus and you can make use of that.which means you have to use the _Deactivate(object sender, EventArgs e) event of the form control to make this work. Since which will trigger when the form loses focus and is no longer the active form. Let Form1 be the form, then the event will be like the following:
private void Form1_Deactivate(object sender, EventArgs e)
{
// Your code here to handle this event
}
One method is to cover the entire screen with a borderless form with the properties set to transparent (a few percent above completely transparent, not sure if total transparency works but you won't notice the difference) and also set to topmost. Then use the events from the form. As soon as a click is detected this will not affect anything underneath the form (which in my application is something I want to happen) but the form could be closed and another mouse click simulated a fraction of a second later to activate the controls that are underneath. I had no problem using the windows API to use mouse hooks in VB6 but cannot seem to find something that works in c# with the 2019 version of .NET so this is a good workaround. Of course to be really clever you could use an irregular forms method to make the transparent form the same shape as the mouse and follow it.
Note: I have just found the complete code to do it using hooks that mere mortals can get up and running at once! KeyboardMouseHooks C# Library - CodePlex Archive
PS if you use my (dumb) method remember to create an escape key or button or you will have to restart your computer unless the form is programmed to disappear for real clicks as suggested!
I know this is late but maybe it helps someone. Using the MouseEventArgs of the MouseUp event of any control you can check for mouse button and wheel among other things. Here is an example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseUp += Form1_MouseUp;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
DoSomething_LeftClick();
}
else if(e.Button == MouseButtons.Right)
{
DoSomething_RightClick();
}
}
private void DoSomething_LeftClick()
{
//Here some code
}
private void DoSomething_RightClick()
{
//Here some code
}
}

stopping event from code C#, call event by user not by code

Sorry, this may be a duplicate question, but I couldnot understand the solutions already provided in different answers.
I have created a mp3 player in a different manner, it plays one mp3 file at a time but one listbox have the chapters, which is not only handling to move position of that particular mp3 but also changes a picturebox image. Now somewhere I need to change the selection of the listbox from a seekbar but dont want to fire the following event of;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
Please guide.
One way to inhibit your selection indexed change event doing its normal way is to use a boolean flag. Also, make sure that this inhibition does not stay around when some exception is raised:
private bool inhibit = true;
private void doSomeProcessWithInhibit()
{
try
{
inhibit = true;
// processing comes here
}
// if something goes wrong, make sure other functionality is not blocked
finally
{
inhibit = false;
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// fast return to reduce nesting
if (inhibit)
return;
// do event handling stuff here
}
P.S. Try to use meaningful names for controls (check listBox1). You will thank yourself when revisiting the code and/or others have to.
Add a Boolean with class scope called something like isProcessing. Set it to true. Do your work, then set it to false. Warp your event in the Boolean:
bool isProcessing = true;
private void switchControls(){
isProcessing = true;
//do work;
isProcessing = false;
}
private void MyControl.OnEvent(object sender, EventArgs e){
if(!isProcessing){
//what you would normally do
}
}
OR....
Deregister the event, the re-register it
private void switchControls(){
myButton1.OnClick -= myButtonClick;
//do work
myButton1.OnClick += myButtonClick;
}

ScatterViewItem manipulation event handlers not being called

I am developing a WPF Surface touchscreen based application which makes use of ScatterViewItem controls.
When using touch input, all manipulations work well: rotation, scaling, translation.
Unfortunately, when I try to execute some code when the manipulations happen, for example the following code in the C# codebehind, nothing happens.
ManipulationDelta += myItemManipulationDelta;
private void myItemManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
Application.Current.Shutdown(); //just to see if it's even happening
}
I have tried adding similar handlers to ManipulationStarting and ManipulationStarted with no success.
Update:
As the answer suggested, I have attempted the following, without success:
public partial class MyControl: ScatterViewItem
{
//constructor for custom control
private void MainWindow_ManipulationDelta2(object sender, ManipulationDeltaEventArgs e)
{
Application.Current.Shutdown();
}
private void MainWindow_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// normal handling of the event.
}
public MyControl()
{
ManipulationDelta += MainWindow_ManipulationDelta2;
ManipulationDelta += MainWindow_ManipulationDelta;
// more stuff ...
}
}
So turns out I had to actually register a ContainerManipulationDelta event inside my custom ScatterViewItem based control in order for the event to fire correctly. Now everything works as expected.

Can I place the mouse event handler on a separate thread?

Can I put a thread on a mouse event handler?
Calls_Calls.MouseUp += new MouseEventHandler(Calls_Calls_MouseUp);
How to add a thread over this?
I would set up the event handler in the same way, but in the Calls_Calls_MouseUp method you can launch a thread to do the work:
private void Calls_Calls_MouseUp(object sender, MouseEventArgs e)
{
ThreadPool.QueueUserWorkItem(state => {
// do the work here
});
}
However, I typically try to have my event handlers as unaware as possible, just calling some other method, often based on some condition:
private void Calls_Calls_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DoSomething();
}
}
private void DoSomething()
{
ThreadPool.QueueUserWorkItem(state => {
// do the work here
});
}
This gives you the ability to trigger the exact same behavior from something else than the MouseUp event on a certain control (so that you can have the same behavior on a menu item, a toolbar button and perhaps a regular command button). It may also open up the possibility to have unit tests on the functionality (even though that is somewhat trickier with asynchronous code).
you can also use BackgroundWorker for this in case you require any updation on the UI for progress and completion.
Calls_Calls.MouseUp+= new MouseEventHandler(delegate(System.Object o, System.EventArgs e) { new Thread(Calls_Call_MouseUp).Start(); });
should work for you. If you get brackets errors, fix them since I handwrote the code :) :)

Adding a ToolTip to an OvalShape in C#

I'm trying to add a tooltip to an OvalShape (Microsoft.VisualBasic.PowerPacks.OvalShape). Since its not a Control, I can't use the simple SetToolTip() method in the ToolTip class. How might I go about showing a ToolTip on an OvalShape? I don't absolutely have to use the ToolTip class if anyone has any better ideas. I'd also like to keep the OvalShape, unless anyone has a better solution that can give me inheritence from Control while keeping a nice circular shape.
You'll have to take advantage of the MouseHover event you can get out of the control. This worked well enough:
bool hoverSeen = false;
private void ovalShape1_MouseHover(object sender, EventArgs e) {
if (!hoverSeen) {
hoverSeen = true;
// Todo, fix position
Point pos = ovalShape1.Parent.PointToClient(Cursor.Position);
toolTip1.Show("On oval", ovalShape1.Parent, pos);
}
}
private void ovalShape1_MouseLeave(object sender, EventArgs e) {
if (hoverSeen) toolTip1.Hide(ovalShape1.Parent);
hoverSeen = false;
}

Categories

Resources