there are a number of examples of dropping master shapes on a document, so that is pretty easy and straightforward.
They all have in common one thing though, you have to supply coordinates to place it. i.e. page.Drop(master, 4, 4)
My question is:
Is there any way to programmatically drop a master, but have the shape attached to the mouse cursor as if you were dragging it off a stencil?
that code can get click coordinates.
QuoteThis code is part of code which originally posted at
' https://translate.google.ru/translate?sl=ru&tl=en&js=y&prev=_t&hl=ru&ie=UTF-8&u=http%3A%2F%2Fvisio.getbb.ru%2Fviewtopic.php%3Ff%3D15%26t%3D671&edit-text=&act=url
Dim WithEvents myapp As Visio.Application
Dim x As Double, y As Double
'Start-up procedure
Sub Start ()
Set myapp = Application
End Sub
'Beginning of the intersecting separation frame - storing coordinates
Private Sub myapp_MouseDown (ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x1 As Double, ByVal y1 As Double, CancelDefault As Boolean)
If Button = 1 Then 'Left mouse button
x = x1: y = y1
End If
End Sub
but i haven't idea how make the program wait when the user clicks ?
Thanks Surrogate
I know how to get the mouse coordinates, but I don't think there is a way to drop a shape without supplying coordinates in the function call.
what I would like to do is something like drop shape function where the shape follows the mouse cursor until it is clicked, then completes.
I'm probably the last person to comment on something like this...have no idea how to use events...but what strikes me about is that mouse events are reactionary, that is, the mouse does something and an event fires. I don't think there are mouse command objects or properties, so you can't attach the shape to the mouse.
Wapperdude
Perry:
I do this trick all the time with my stencil-based macros.
I start with a Mouse Up window event in the stencil's ThisDocument module that stores the mouse X and Y in the document's shapesheet as follows:
Public WithEvents EventWindow As Visio.Window
Private Sub EventWindow_MouseUp(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
Dim TheDocument As Document
Dim TheDocumentSheet As Shape
Set TheDocument = ActiveDocument
Set TheDocumentSheet = TheDocument.DocumentSheet
If Not TheDocumentSheet.CellExists("User.MouseX", 0) Then
TheDocumentSheet.AddNamedRow(visSectionUser, "MouseX", 0)
End If
If Not TheDocumentSheet.CellExists("User.MouseY", 0) Then
TheDocumentSheet.AddNamedRow(visSectionUser, "MouseY", 0)
End If
TheDocumentSheet.Cells("User.MouseX").Formula = x
TheDocumentSheet.Cells("User.MouseY").Formula = y
End Sub
Next, on the master shape, on its shapesheet, in the EventDrop cell, I have a call to a stencil macro, =CALLTHIS("ThisDocument.Dropped","Kencil"), where "Kencil" is the name of my stencil , and "Dropped" is defined in the stencil's ThisDocument module as follows:
Public Sub Dropped(ByRef TheDroppedShape As Visio.Shape)
Dim TheDocument As Document
Dim TheDocumentSheet As Shape
Set TheDocument = ActiveDocument
Set TheDocumentSheet = TheDocument.DocumentSheet
TheDroppedShape.Cells("PinX").Formula = TheDocumentSheet.Cells("User.MouseX").Formula
TheDroppedShape.Cells("PinY").Formula = TheDocumentSheet.Cells("User.MouseY").Formula
End Sub
My apologies, but I did not test this code. I'd post the original out of my Kencil, but it has a lot of other stuff that obfuscates the simplicity of the task. But this should point you in the right direction--I hope.
- Ken
Quote from: Hey Ken on February 23, 2017, 02:15:48 PM
Perry:
I do this trick all the time with my stencil-based macros.
I start with a Mouse Up window event in the stencil's ThisDocument module that stores the mouse X and Y in the document's shapesheet as follows:
Public WithEvents EventWindow As Visio.Window
Private Sub EventWindow_MouseUp(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
Dim TheDocument As Document
Dim TheDocumentSheet As Shape
Set TheDocument = ActiveDocument
Set TheDocumentSheet = TheDocument.DocumentSheet
If Not TheDocumentSheet.CellExists("User.MouseX", 0) Then
TheDocumentSheet.AddNamedRow(visSectionUser, "MouseX", 0)
End If
If Not TheDocumentSheet.CellExists("User.MouseY", 0) Then
TheDocumentSheet.AddNamedRow(visSectionUser, "MouseY", 0)
End If
TheDocumentSheet.Cells("User.MouseX").Formula = x
TheDocumentSheet.Cells("User.MouseY").Formula = y
End Sub
Next, on the master shape, on its shapesheet, in the EventDrop cell, I have a call to a stencil macro, =CALLTHIS("ThisDocument.Dropped","Kencil"), where "Kencil" is the name of my stencil , and "Dropped" is defined in the stencil's ThisDocument module as follows:
Public Sub Dropped(ByRef TheDroppedShape As Visio.Shape)
Dim TheDocument As Document
Dim TheDocumentSheet As Shape
Set TheDocument = ActiveDocument
Set TheDocumentSheet = TheDocument.DocumentSheet
TheDroppedShape.Cells("PinX").Formula = TheDocumentSheet.Cells("User.MouseX").Formula
TheDroppedShape.Cells("PinY").Formula = TheDocumentSheet.Cells("User.MouseY").Formula
End Sub
My apologies, but I did not test this code. I'd post the original out of my Kencil, but it has a lot of other stuff that obfuscates the simplicity of the task. But this should point you in the right direction--I hope.
- Ken
Thanks Ken, but that is not really what I am looking for
Quote from: wapperdude on February 23, 2017, 02:18:51 AM
I'm probably the last person to comment on something like this...have no idea how to use events...but what strikes me about is that mouse events are reactionary, that is, the mouse does something and an event fires. I don't think there are mouse command objects or properties, so you can't attach the shape to the mouse.
Wapperdude
Yeah, it's dumb that the DROP method requires pre-defined coordinates.
what if those pre-defined coordinates are the upper left corner of the drawing and the user is zoomed into the lower right corner. when he runs the command he'll never see the shape get dropped.
Lame!
One may wonder why I want to do this in code, since you can just drag a master off a stencil with the effect that I want.
What I need to do is pull one master out of the stencil, then pull another shape off the stencil and place it into the first one, thereby creating a group which I then want to drag to its location on the page. The configuration of this group can change depending on user input so I cant just put all these grouped objects in the stencil.
An idea occurred to me, but haven't tried in code yet. Maybe this could work. I will try to drop the master in some location way off the page where it likely wont be seen, then drop the other shapes into it, make the group. Then with the group selected, constantly update its PinX and PinY cells based on input from a mouse listener. When the user clicks, quit updating those cells and turn off the mouse listener.
Does this sound do-able?
Well, why did cross my mind.
Using the Window.GetWindowReectangle method ought to allow you to determine a set of coordinates within the viewing window. You could drop your shapes to desired coordinate, group, and since viewable, grab and locate as needed. This is for newer Visio versions, so, I can't discuss it. https://msdn.microsoft.com/en-us/library/office/ff765668.aspx (https://msdn.microsoft.com/en-us/library/office/ff765668.aspx)
Wapperdude
Can't you drag your initial shape from the stencil and drop it where you want it, then programatically take your other shape from the stencil and group it into the original dropped shape.
Quote from: AndyW on February 24, 2017, 02:12:01 PM
Can't you drag your initial shape from the stencil and drop it where you want it, then programatically take your other shape from the stencil and group it into the original dropped shape.
You could do that, of course, but that is not what I want to do.
This is going to be a command function in a larger visio addin for adding electrical connectors to a sheet.
the user selects a connector from the database and it is inserted.
I don't want the command to ask the user to select a connector from the database and then ask him to drag stuff from a stencil (which may or may not be loaded/visible)
Connectors say you. Tell us a little more or show a couple examples of variants. This might be do-able with a single smartshape. There have been several different style/versions done on the forum.
Wapperdude
You could use OLE drag-n-drop, drag something off your form, then tracking the mouse events put your shape at the drop location on you diagram.
https://youtu.be/apUZ1Xt3EKc (https://youtu.be/apUZ1Xt3EKc)
Quote from: wapperdude on February 25, 2017, 12:12:57 AM
Connectors say you. Tell us a little more or show a couple examples of variants. This might be do-able with a single smartshape. There have been several different style/versions done on the forum.
Wapperdude
These are connectors used in aviation equipment. Typically Mil Spec or our custom D-subs. they can have a few as 9 contacts or over 100.
The contacts (pins or sockets) and the connector symbol will be part of a group with custom properties. A sql database will track how many contacts are shown. A connector can be "broken", i.e. part of it shown on one page, another part of it shown somewhere else but it would still be considered the same physical connector by the database. The user may choose to show all the contacts or just some. So unused contacts can still be used later by inserting another portion of the connector. When a visio connector object is attached to a contact, it sets a flag for that contact in the database as being used. This allows for creating reports on how many connectors are in a project and how many of their contacts are "hooked up". I also generate wire reports on all visio connector objects which are "wires" and their to-from.
I have attached a small drawing showing a couple of variations.
Quote from: wapperdude on February 24, 2017, 12:28:56 AM
Well, why did cross my mind.
Using the Window.GetWindowReectangle method ought to allow you to determine a set of coordinates within the viewing window. You could drop your shapes to desired coordinate, group, and since viewable, grab and locate as needed. This is for newer Visio versions, so, I can't discuss it. https://msdn.microsoft.com/en-us/library/office/ff765668.aspx (https://msdn.microsoft.com/en-us/library/office/ff765668.aspx)
Wapperdude
looks like that wont work with visio 2007, which I am stuck with.
I am busy with a Solidworks project right now. when I'm done I will get back to my mad visio experiments!
Actually, does work with V2007. Try this code:
Sub MoveShp2CntrView()
Dim lVz As Double, tVz As Double, wVz As Double, hVz As Double
Dim locX As Double, locY As Double
Dim vsoShp As Shape
Visio.ActiveWindow.GetViewRect lVz, tVz, wVz, hVz
' Debug.Print "Current View Window: " & lVz, tVz, wVz, hVz
'Calculate center of View:
locX = lVz + 0.5 * wVz
locY = tVz - 0.5 * hVz
' Debug.Print locX, locY
'Use shape based upon selection:
' Set vsoShp = ActiveWindow.Selection(1)
' vsoShp.CellsU("PinX").FormulaU = locX
' vsoShp.CellsU("PinY").FormulaU = locY
'Use shape based upon ID:
Set vsoShp = ActivePage.Shapes.ItemFromID(1)
ActiveWindow.Select vsoShp, visSelect 'Optional: this makes the shape ACTIVE
vsoShp.CellsU("PinX").FormulaU = locX
vsoShp.CellsU("PinY").FormulaU = locY
End Sub
Wapperdude
Quote from: wapperdude on February 25, 2017, 12:12:57 AM
Connectors say you. Tell us a little more or show a couple examples of variants. This might be do-able with a single smartshape. There have been several different style/versions done on the forum.
Wapperdude
do tell
Quote from: wapperdude on February 24, 2017, 12:28:56 AM
Well, why did cross my mind.
Using the Window.GetWindowReectangle method ought to allow you to determine a set of coordinates within the viewing window. You could drop your shapes to desired coordinate, group, and since viewable, grab and locate as needed. This is for newer Visio versions, so, I can't discuss it. https://msdn.microsoft.com/en-us/library/office/ff765668.aspx (https://msdn.microsoft.com/en-us/library/office/ff765668.aspx)
Wapperdude
I'm not sure how the Window.GetWindowReectangle is going to help me.
I have already got my shapes dropped and grouped on the page. The thing I cant figure out is how to move them around on the page with the mouse cursor.
code like this does NOT work
'while mouse left button is NOT down...
While mouseDownForConnector = False 'mouseDownForConnector is a global boolean variable
'mouseDownForConnector is set to true and false by the mousehandler events
groupShape.CellsU("PinX").FormulaU = mouseHandler.xPos.ToString() & " in"
groupShape.CellsU("PinY").FormulaU = mouseHandler.yPos.ToString() & " in"
End While
it just goes into an endless loop.
it seems that the group I create does not actually appear on the page until the function is completed.
maybe I should be trapping the shape drop event and trying to do my moving there (assuming the shape dropped is the one I want)
Quote from: perry59 on March 01, 2017, 11:37:43 PMit just goes into an endless loop.
not sure that your task impossible in visio because there haven't special event for get mouse click coordinate.
For example AutoCAD have GetPoint Method (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2017/ENU/AutoCAD-ActiveX/files/GUID-5C8BA75E-5F87-479B-B167-3961F93E617E-htm.html) which stoped code execution until then define point
Quote from: Surrogate on March 01, 2017, 11:52:04 PM
Quote from: perry59 on March 01, 2017, 11:37:43 PMit just goes into an endless loop.
not sure that your task impossible in visio because there haven't special event for get mouse click coordinate.
For example AutoCAD have GetPoint Method (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2017/ENU/AutoCAD-ActiveX/files/GUID-5C8BA75E-5F87-479B-B167-3961F93E617E-htm.html) which stoped code execution until then define point
Good 'ole AutoCAD!
@Perry59: did you look at the code snippet I provided? Well, please look at the attached file.
The macro draws two squares. Then it groups them. After grouping, the move shape macro is called.
To demonstrate: start with just the oval shape visible. More dramatic that way. Then, zoom in on the oval, about 500X. Reposition the window so the oval is NOT centered in the viewing window. Now, run the macro. Phoosh! A group of 2 squares appears centered in the screen. The group is still selected. Mouse over, push left button down, drag the group to desired location. NO mouse events necessary.
Wapperdude
Quote from: wapperdude on March 02, 2017, 12:42:24 AM
@Perry59: did you look at the code snippet I provided? Well, please look at the attached file.
The macro draws two squares. Then it groups them. After grouping, the move shape macro is called.
To demonstrate: start with just the oval shape visible. More dramatic that way. Then, zoom in on the oval, about 500X. Reposition the window so the oval is NOT centered in the viewing window. Now, run the macro. Phoosh! A group of 2 squares appears centered in the screen. The group is still selected. Mouse over, push left button down, drag the group to desired location. NO mouse events necessary.
Wapperdude
Yes I have seen that. Thanks for posting.
Perhaps I have not been clear in what I am trying to achieve (which I am afraid is probably not possible in the visio API)
I have no problem in programmatically dropping shapes on the sheet, or moving them once they are there.
what I want to do is that immediately after the shape appears, it is "attached" to the mouse cursor and follows the mouse cursor until the user clicks, then it is set at that location.
Again, probably not possible, I may have to change my approach to the problem.
-Perry
I think we're splitting hairs here. I understand you know how to drop, group, and move. The issue is attaching to the mouse. Presumably, there are occasions when the drop/group may take place outside of user view, i.e., off screen. And, the mouse will be within user view. Hence, assign the group to the mouse and the group pops into view, attached to the mouse, and the user can drag to desired location and place.
I don't think you can do the attach to mouse, nor do I think it's necessary. That was the point of the file and it's demo. The macro replicates your drop/group, which, for the demo is off view screen. Then, wherever the user is viewing, the group is moved to that location. The group remains selected. So, yes, the user must mouse over, left click, drag and position as desired. That's minimal user interaction. The user knows the shape will be center screen. This ought to satisfy 98% of your requirements. Plus, the code is quite simple.
Wapperdude
Quote from: wapperdude on March 02, 2017, 05:01:52 PM
I think we're splitting hairs here. I understand you know how to drop, group, and move. The issue is attaching to the mouse. Presumably, there are occasions when the drop/group may take place outside of user view, i.e., off screen. And, the mouse will be within user view. Hence, assign the group to the mouse and the group pops into view, attached to the mouse, and the user can drag to desired location and place.
I don't think you can do the attach to mouse, nor do I think it's necessary. That was the point of the file and it's demo. The macro replicates your drop/group, which, for the demo is off view screen. Then, wherever the user is viewing, the group is moved to that location. The group remains selected. So, yes, the user must mouse over, left click, drag and position as desired. That's minimal user interaction. The user knows the shape will be center screen. This ought to satisfy 98% of your requirements. Plus, the code is quite simple.
Wapperdude
That's true.
what I originally wanted is probably not possible.
I'll have to modify my desires!
Life is full of compromises! :-\
Quote from: wapperdude on March 02, 2017, 06:37:05 PM
Life is full of compromises! :-\
That it is, but at least I can drop my shape where the user will see it!
Thanks