Tuesday, February 13, 2007

XAML Window Positioning with Dragging

Many forums have users ask about repositioning a Windows Form application around by means of dragging inside the window. I started seeing more questions about this with regards to XAML projects in Blend and Visual Studio. It can be done very easily with use of a Timer control. If you know of an even simpler way of accomplishing this please let me know.

First you will need to add a reference to the System.Windows.Forms and System.Drawing namespaces. The Drawing namespace would only be required if you want to enable snapping to the edges of your screen. I'll discuss this later though.

Add a timer control with events into the code. You will also need to add two doubles to hold the initial position of your cursor.


 


 

Private
WithEvents DragTimer As Windows.Forms.Timer

Dim initY As
Double

Dim initX As
Double


 

Within the New method, initialize the timer and give it an interval of 5 milliseconds.


 

Public
Sub
New()


MyBase.New()


 


Me.InitializeComponent()


 

DragTimer = New Windows.Forms.Timer

DragTimer.Interval = 5

End
Sub


 

You will need to determine position of the cursor relative to the form. I believe there is a property already out there for this but I don't remember it so just create to functions.


 

Private
Function TopDistance() As
Double


Return (Windows.Forms.Cursor.Position.Y - Me.Window.Top)

End
Function


 

Private
Function LeftDistance() As
Double


Return (Windows.Forms.Cursor.Position.X - Me.Window.Left)

End
Function


 

All that is left now is the two methods needed to handle the main windows MouseUp and MouseDown events and the method to handle the timer's Tick event. The MouseDown event handler will set the initial cursor position values relative to the actual form. It will then turn on the timer. The MouseUp event handler simply turns the timer off. The Tick event will trigger the actual forms location change.


 

Private
Sub Window1_MouseDown(ByVal sender As
Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles
Me.MouseDown

initY = TopDistance()

initX = LeftDistance()


 

DragTimer.Enabled = True

End
Sub


 

Private
Sub Window1_MouseUp(ByVal sender As
Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles
Me.MouseUp

DragTimer.Enabled = False

End
Sub


 

Private
Sub DragTimer_Tick(ByVal sender As
Object, ByVal e As System.EventArgs) Handles DragTimer.Tick


Me.Window.Top = Windows.Forms.Cursor.Position.Y - initY


Me.Window.Left = Windows.Forms.Cursor.Position.X - initX

End
Sub


 

If you have the need to restrain only the movement on the x or y plane, simply remove the corresponding line in the Tick event.

InfoPath Browser Enabled Forms with Event Handled Security Control

After installing MOSS 2007 and the forms server I came upon the need to have custom item level security. This depended on the type of form as well as the content within the form. For example, human resources might have confidential documents which need to be signed by some users but not accessible by others. This would be possible if I had a library for each department and each form. Then there are medical situations which only the director of human resources is legally allowed to view. There seem to be little slight workarounds to get you just a little further only to run into something else. This drove me to want to control everything in code. I was aiming for a slightly generic event and didn't want a separate event to register for Medical forms so I just added it in here. I know this could be broken up better but everything seems so touchy and my current setup doesn't allow for debugging.

To register this event I suggest using the Event Handler Explorer which is a free tool that works great. If you want to hook in the event yourself here is a great quick article to do so. I tried to comment the code heavily so it would be fairly simple to customize to your needs. If you want to read a good article about user roles check this out.


 

Public
Overrides
Sub ItemAdded(ByVal properties As Microsoft.SharePoint.SPItemEventProperties)


MyBase.ItemAdded(properties)



'Create a SPWeb object

Dim web As Microsoft.SharePoint.SPWeb = properties.OpenWeb()




'Create an object for the SPListItem.


Dim ListItem As Microsoft.SharePoint.SPListItem = properties.ListItem




'The InfoPath form library has a column Employee Name which is created


'with the publish wizard. In my case it holds the domain\username of


'the user who created the form.


Dim UserName As
String = ListItem("Employee Name").ToString()




'Create a blank SPUser to hold the info for the person in the Employee Name


'column.


Dim User As Microsoft.SharePoint.SPUser




Try


'Must try to pull the user from the SiteUsers property.


'If the user is not in the SharePoint users it will


'throw an exception. Take that time to add the user.

User = web.SiteUsers(UserName)


Catch ex As Exception


Dim UserGroup As
New ucintranet.UserGroup


Dim Email As
String = MyWebService.GetEmail(UserName)


Dim FullName As
String = MyWebService.GetFullName(UserName)






'Somehow you must find the users email and fullname from


'the username. I did it with a web service which reads from


'Active Directory.


'Add the user to the SiteUsers property.

web.SiteUsers.Add(UserName, Email, FullName, String.Empty)


'Update the web object.

web.Update()




'Might not be nessisary but just making sure


'that the SP user collection is reloaded with


'the addition.

web.Close()

web = properties.OpenWeb()


End
Try


Try


'Try again to load the user.

User = web.SiteUsers(UserName)


Catch ex As Exception


Throw
New Exception("User failed to add to site collection.", ex)


End
Try




'Get a Contributor Role Definition from SPWeb (or whatever role you needed)


Dim ContributorRoleDefinition As Microsoft.SharePoint.SPRoleDefinition = web.RoleDefinitions.GetByType(Microsoft.SharePoint.SPRoleType.Contributor)




'Create new Role Assignment


'Add Role Definition to Role Assignment's Role Definition Binding. If you


'had multiple users you needed to give access to, you would just add more


'RoleAssignment objects with the specific SPUser object.


Dim UserRoleAssignment As
New Microsoft.SharePoint.SPRoleAssignment(User)

UserRoleAssignment.RoleDefinitionBindings.Add(ContributorRoleDefinition)








'This section is less than optimal but I just finished it


'and it works.


'Check for medial information, if present then don't use


'existing permissions as template (This strips all of the


'current site users and groups out of the item).




'Create a boolean object to determine if this form even deals


'with medical info. If it doesn't than the try will fail setting


'the EvalMedical object to false.


Dim EvalMedical As
Boolean = True


Dim Medical As
String = String.Empty


Try


'Contains Medical Information is the column name for the second


'field published as a column (T/F) through the publish wizard.

Medical = ListItem("Contains Medical Information").ToString()


Catch ex As Exception


'If it failed then there was no Contains Medical Information


'column present.

EvalMedical = False


End
Try




'If the column was present, this doesn't mean that it needs to


'apply the strict rules.


If EvalMedical Then


'If the Medical object is true than the RoleAssignments


'will not be copied therefore leaving an empty permission


'set for the item.

ListItem.BreakRoleInheritance(Not
CBool(Medical))




'This next object will hold the SPGroup of the HRDirector who needs


'access to the form. We create a new SPRoleAssignment object to hold


'the access level for the group and then add it to the SPListItem.


Dim Group As Microsoft.SharePoint.SPGroup = web.SiteGroups("HR Director")


Dim HRRoleAssignment As
New Microsoft.SharePoint.SPRoleAssignment(Group)

HRRoleAssignment.RoleDefinitionBindings.Add(ContributorRoleDefinition)

ListItem.RoleAssignments.Add(HRRoleAssignment)


ElseIf
Not ListItem.HasUniqueRoleAssignments Then


'Regardless, if the SPListItem has unique role assignments


'than they need to be broken, the RoleAssignments will be


'inherited though.

ListItem.BreakRoleInheritance(True)


End
If




'Add Role Assignment to SPListItem's Role Assignment Collection

ListItem.RoleAssignments.Add(UserRoleAssignment)




'One final update to the SPListItem.

ListItem.Update()


End
Sub