MyFavouriteThings project update,

Tuesday, 18 November 2008 14:43 by frimbooze

I have been working on my project where I can and I have decided on a JavaScript Library for the project. The winner was jquery, due to a recent decision by Microsoft ‘jquery will be the official script library for asp projects and as such there is a patch to add intellisense for jquery, this obviously helps development of custom JavaScript widgets.

I have been doing research and found the following sites helpful:

 ClassDiagram1

I have prototyped the methods for the web-service, No other code is yet implemented, I will use these prototypes to build custom ajax calls using the jquery methods and not the built in script manager.  Hopefully then after creating the data objects in JavaScript I will be able to test these methods and see the resulting post data they generate and in the web services test if the ajax calls product expected input and output using magic data.

What to do next?

  • Code the Data objects in javascript.
  • Code custom ajax calls.
  • Test input and output for these calls.
  • Design template for the site.
  • Mock-up the interfaces for adding, removing and updating.
  • Look at UI tools offered by jquery UI.

Currently rated 3.0 by 5 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (541) | Comment RSSRSS comment feed

My Favourite Things

Friday, 24 October 2008 13:25 by frimbooze

I altered a requirement of the project, Originally I decided that I would only have one implementation of each time e.g only one category of type book. I was thinking that I would rather have many instances of each type. Say I wanted to have favourites book list and a 2nd books I hate list. This would have been impossible with my first implementation.

I have altered the DB schema accordingly. There is now a table for each type that will store each instance as a row, the instance data is serialized into Json. I have not normalizing the data further and thus have avoided second and third tables for each category.

Each type needs its own DB class which cannot be generic as specific SQL queries are needed for each type. I have implement and interface ICategory.

ClassDiagram1 

Each Type will implement this interface and the IErrorLog which contains a simple method to log each exception in a textfile.

Each Type is able to save an instance of itself into a SQLite table. Now all we need is a generic collection to interact with.

ClassDiagram1

This generic collection when created gather all items in the DB for that type and de-serialize them into a collection. Any items added removed or updated will be altered in the DB table as well.

The main purpose of this collection is to provide and abstraction to the DB and allow all instances to be serialized and sent to the client. A data-table could be used in this collections place.

What’s Next?

  • Test, must write a test for these interfaces and magic data for each type.
  • Implement the interfaces IErrorLog and ICategory in all category types, 8 in all

Currently rated 3.0 by 5 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (297) | Comment RSSRSS comment feed

Favourite Things- Data Package

Friday, 10 October 2008 11:18 by frimbob

I have been working on this project in my spare time for a few weeks now, as I mentioned in a previous post , I have define a number of data classes and have decided to use an SQL Lite DB as a robust data store.

I built a simple data-class to handle the transactions to the DB.

image

The class consisted of a few methods that execute a pre-built sql command, 2 method in which to build the SQLLiteCommand object and some public methods to return a category and an image.

Handling Images

I wanted my application to store images in a separate table for performance reasons, a http handler could then be used to return an image. Since the images will upload as a byte stream , it is very easy to store them in the DB.

Going to make some changes

Last night I was thinking that wouldn't it be great if I could create multiple instances of each type on the client side. Say for example I wanted to create a ’list of books I hate’ the data is still of type books, but since my current DB schema only supports one category of a particular type this would be impossible.

How to Fix?

Again not too difficult I will have to move each type out of a single table and into its own, then I could store each instance in the table as a serialized JSON stream. I will need to create Collection class for each type, able to read the data from the DB and de-serialize into a collection.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (421) | Comment RSSRSS comment feed

New Project: My Favourite Things

Friday, 19 September 2008 14:56 by Frimbob

I have been wanting to try this for a while, I have wanted an easy way to create lists of my Favourite; movies , books, songs etc and display them on my Blog, now I could just do a couple of blog posts but my lists change very quickly and its would just become a time issue.

I wanted to attempt a ajax app, so my a project that would allow me to use ajax techniques with a persistent data store seem in fruition, I could then dynamically display the lists and a have an easily modify control.

Quickly I have some requirements.

  1. Use the .Net 3.5, framework
  2. Blog use a flat file so must this datastore.
  3. Use JSON and not xml as data format.
  4. Use AJAX techniques.
  5. YUI library components for the script.

I have identified 3 packages:

  • Library which handle object definitions and persistence.
  • Web-services that provide the access layer.
  • Client Side package to display and allow control.  

Nothing too ground breaking about that setup, I have made good inroads into the first data layer.

Objectives of Data Layer

  • It must accept string paramaters and return JSON string.
  • Handle all transactions and object Deinitions.
  • Provide a robust data-store.

I have decided to use the following libraries for this package.

  • Json.net - This provides the Json TO .Net Object mapping. Is better than the inbuilt Json parser IMOP.
  • SQLlite ado.net Provider - This provide the flat-file DB and help ensure transactional and data integrity.

The Data-Definitions

This is hierarchal data, With each category and items under the category. I have defined 2 base cases that cover the common data between each category. Below is a print out of these two classes

ClassDiagram1

The 'CategoriesBase' implements 2 important static generic  methods. The first is a Serialize obj to json, which as its name suggest return a json string from an object.

The 2nd method is the reverse, De-serialize takes a Json string and returns an object.

These classes are still a work in progress but I will require a method that will store and object in the DB an other to retrieve it.

The Sub-Classes

I have created a number of categories and items.

  • Albums
  • Books
  • Drinks
  • Movies
  • Recepies
  • Songs
  • Sports
  • TVShows

ClassDiagram2

Observations

  • By Hard Coding the data-objects, I make adding new ones more difficult.
  • The DB will consists of a single table with each category consuming one column, The objects state will be mapped to a single record and stored in JSON text string.
  • I'm working on an object level, To edit and 'item' I will have to restore the state of the category first.
  • No be appropriate for complex structures.
  • Using DB over the .net streamwriter or and XML data-store(my first choice) gives Transaction integrity where none would have existed and easier to backup a single file than 5 or six.

Jobs to Come

I still must develop an DB helper class to handle the transaction to the DB file and obviously needs some magic data to test the methods.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , , , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (551) | Comment RSSRSS comment feed

Word Menus Update:

Friday, 20 June 2008 22:19 by frimbob

I have modified the code that I used to create a word menu to build a dynamic version of the previous code. The Application uses an xml file to store the names and location of a list of word-documents that need a menu button.

XML_File


   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <templates>
   4:     <name location="c:\template1.dot">Template1</name>
   5:     <name location="c:\template2.dot">Template2</name>
   6:     <name location="c:\template3.dot">Template3</name>
   7:     <name location="c:\template4.dot">Template4</name>
   8:   </templates>
   9: </configuration>

I then built a simple class to load and parse the xml file. The class uses and event handler to send the results to other class that are registered. (really an experiment for a delegate call back used in implementing patters like the observer, just for the practice).

ConfigData


   1: Imports System.Xml
   2: Imports System.Xml.Serialization
   3: Imports System.IO
   4:  
   5: '<summary> Reads a Config XmlFile and provides its data as Properties </summary>
   6: Public Class ConfigFile
   7:  
   8: #Region "Private Members"
   9:  
  10:     'Private Members
  11:     Dim TemplateNames_Collection As New System.Collections.Generic.Dictionary(Of String, String)
  12:     Dim objxmlDocument As New XmlDocument
  13:     Dim objRootNode As XmlNode
  14:  
  15:     Delegate Sub UpdateHandler(ByVal sender As Object)
  16:     Public Event UpdateEvent As UpdateHandler
  17:  
  18: #End Region
  19:  
  20: #Region "Properties"
  21:  
  22:     'Declare Properties
  23:     ReadOnly Property TemplateCollection() As System.Collections.Generic.Dictionary(Of String, String)
  24:         Get
  25:             Return TemplateNames_Collection
  26:         End Get
  27:     End Property
  28:  
  29: #End Region
  30:  
  31: #Region "Public Methods"
  32:  
  33:     Public Sub ReadXMLFile()
  34:         'declarations
  35:         Dim objRootChildNodes As XmlNodeList
  36:  
  37:         'get values out of the file and into the dataStructure
  38:         objRootChildNodes = objRootNode.ChildNodes
  39:  
  40:         For Each xmlnode As System.Xml.XmlNode In objRootChildNodes
  41:             For Each xmlNode2 As System.Xml.XmlNode In xmlnode.ChildNodes
  42:                 Dim strNodeValue As String = xmlNode2.InnerText
  43:                 Dim strNodeLocation As String = xmlNode2.Attributes.ItemOf(0).Value
  44:                 TemplateNames_Collection.Add(strNodeValue, strNodeLocation)
  45:             Next
  46:         Next
  47:  
  48:         RaiseEvent UpdateEvent(Me) ' Call the update Event
  49:  
  50:     End Sub
  51:  
  52: #End Region
  53:  
  54: #Region "Constructor"
  55:  
  56:     Public Sub New()
  57:         'loadtheXmlFile 
  58:         objxmlDocument.Load("C:\Users\Guest\Documents\Visual Studio 2005\Projects\WordAddIn1\WordAddIn1\Custom Classes\XMLFile1.xml")
  59:         objRootNode = objxmlDocument.DocumentElement
  60:     End Sub
  61:  
  62: #End Region
  63:  
  64:  
  65: End Class
  66:  

I used the collection in the above class in a For Each loop.  This loop creates a new commandbutton , which is then stored in an array declared at the class level. If the button object where not stored in the array they would go out of scope when the function ends and only the last instance of the button would still exist.

MenuBuilder


   1: Public Class MenuBuilder
   2:  
   3: #Region "Declarations"
   4:  
   5:     Private TemplateCollection As System.Collections.Generic.Dictionary(Of String, String)
   6:     Private MenuTag As String = "Air Stories Helper Program"
   7:     Dim menuCommand() As Office.CommandBarButton
   8: #End Region
   9:  
  10: #Region "properties"
  11:     Private thisapp As Word.Application
  12:     Public Property ThisApplication() As Word.Application
  13:         Get
  14:             Return thisapp
  15:         End Get
  16:         Set(ByVal value As Word.Application)
  17:             thisapp = value
  18:         End Set
  19:     End Property
  20:  
  21: #End Region
  22:  
  23: #Region "Public Methods"
  24:     'loads the controls on the toolbar
  25:     Public Sub LoadData(ByVal subject As Object)
  26:         Dim configData As ConfigFile = TryCast(subject, ConfigFile)
  27:         If Not IsNothing(configData) Or Not IsDBNull(configData) Then
  28:             TemplateCollection = configData.TemplateCollection
  29:         End If
  30:     End Sub
  31:  
  32:  
  33:     Public Sub LoadControls()
  34:  
  35:         'Test for data
  36:         If Not IsNothing(TemplateCollection) Then
  37:             'check if menu bar exists function
  38:             Call CheckIfMenuBarExists()
  39:  
  40:             'load function
  41:             Call AddMenuBar()
  42:         Else
  43:             MessageBox.Show("No menu data present plese contant Administrator")
  44:  
  45:         End If
  46:     End Sub
  47:  
  48:     ' Create the menu, if it does not exist.
  49:     Private Sub AddMenuBar()
  50:         Try
  51:             Dim menuBar As Office.CommandBar = WordAddIn1.Globals.ThisAddIn.Application.CommandBars.ActiveMenuBar
  52:             Dim menuCaption As String = "AIR Template Menu"
  53:             Dim intcounter As Integer = 0
  54:  
  55:             If menuBar IsNot Nothing Then
  56:                 Dim cmdBarControl As Office.CommandBarPopup = Nothing
  57:                 Dim controlCount As Integer = menuBar.Controls.Count
  58:  
  59:                 ' Add the new menu.
  60:                 cmdBarControl = CType(menuBar.Controls.Add(Type:=Office.MsoControlType.msoControlPopup, Before:=controlCount, Temporary:=True),  _
  61:                     Office.CommandBarPopup)
  62:                 cmdBarControl.Caption = "AirStories"
  63:                 cmdBarControl.Tag = MenuTag
  64:  
  65:                 For Each item As String In TemplateCollection.Keys
  66:                     Dim Button As Office.CommandBarButton
  67:                     'Add the menu command.
  68:                     Button = CType(cmdBarControl.Controls.Add(Type:=Office.MsoControlType.msoControlButton, Temporary:=True), Office.CommandBarButton)
  69:                     With Button
  70:                         .Caption = item.ToString
  71:                         .Tag = item.ToString
  72:                         .FaceId = 300
  73:                     End With
  74:                     AddHandler Button.Click, AddressOf menuCommand_Click
  75:                     ReDim Preserve menuCommand(intcounter) ' re-size the array
  76:                     menuCommand(intcounter) = Button
  77:                     intcounter = intcounter + 1 ' increment the counter       
  78:                 Next
  79:  
  80:             End If
  81:         Catch ex As Exception
  82:             MessageBox.Show(ex.Message)
  83:         End Try
  84:     End Sub
  85:  
  86:  
  87: #Region "Constructor"
  88:     Public Sub New()
  89:  
  90:  
  91:     End Sub
  92: #End Region
  93:  
  94: #End Region
  95:  
  96: #Region "Private Methods"
  97:  
  98:     ' If the menu already exists, remove it.
  99:     Private Sub CheckIfMenuBarExists()
 100:         Try
 101:             Dim foundMenu As Office.CommandBarPopup = thisapp.Application.CommandBars.ActiveMenuBar.FindControl(Office.MsoControlType.msoControlPopup, Tag:=MenuTag, Visible:=True, Recursive:=True)
 102:             If foundMenu IsNot Nothing Then
 103:                 foundMenu.Delete(True)
 104:             End If
 105:  
 106:         Catch ex As Exception
 107:             MessageBox.Show(ex.Message)
 108:         End Try
 109:     End Sub
 110:  
 111:  
 112:     'Method to verify the template location
 113:     Private Function VerifyTemplateLoc(ByVal Template As String) As Boolean
 114:         Dim Applic As Word.Application = Globals.ThisAddIn.Application
 115:  
 116:         'split the file name and the location
 117:         Dim TemplateSplit() As String = Template.Split("\")
 118:         Dim fname As String = TemplateSplit(TemplateSplit.Length - 1)
 119:         Dim flocation As String = Template.Replace(fname, "")
 120:         flocation = flocation.Trim()
 121:  
 122:         'found bool
 123:         Dim found As Boolean = False 'default is false
 124:         Try
 125:             Applic.System.Cursor = Word.WdCursorType.wdCursorWait
 126:             With Applic.FileSearch
 127:                 .FileName = fname
 128:                 .LookIn = flocation
 129:                 .SearchSubFolders = True
 130:                 If .Execute() = 1 Then
 131:                     found = True
 132:                 Else
 133:                     found = False
 134:                 End If
 135:             End With
 136:         Finally
 137:             Applic.System.Cursor = Word.WdCursorType.wdCursorNormal
 138:         End Try
 139:         Return found 'return bool
 140:     End Function
 141:  
 142:     Private Sub Newdocument(ByVal location As String)
 143:         
 144:         MessageBox.Show(location.ToString)
 145:  
 146:     End Sub
 147:  
 148: #End Region
 149:  
 150: #Region "Event Handlers"
 151:  
 152:     'click event for our custom menu
 153:     Private Sub menuCommand_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, _
 154:         ByRef CancelDefault As Boolean)
 155:  
 156:         MessageBox.Show("woank")
 157:      End Sub
 158:  
 159:  
 160: #End Region
 161:  
 162:  
 163: End Class

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (553) | Comment RSSRSS comment feed

Jukebox Project

Thursday, 12 June 2008 14:01 by frimbob

Having bought a very large LCD monitor last December a 26 inch LCD monitor that is and just regretting it a little upon finding that it was really a television not  an up close and personal computer screen but it was cheap and very appealing at the time. Well I just could not let such a large screen go to waste.

The project build a Jukebox for my bedroom,  its got use my existing components , have a remote of sorts and be quiet and low energy as possible.

Existing Components


n2640wb_m 

Vewsonic 26inch LCD Monitor

 

 

 

 

 

 

blog_120608_4

 

 

VIA Mini-ITX ML 1000 

 

 

 

 

 

blog_120608_5 

 

Lian Li PC-9100

 

 

 

 

 

 

 

New Items


blog_120608

 

 

Logitech diNovo Mini

 

 

 

blog_120608_1

 

1GB PC2100 Memory

 

 

 

blog_120608_2

 

 

Pioneer Slime Line DVD-Burner

 

 

 

 

  blog_120608_3

 

 

 

ATA 320Gb HDD

 

 

 

The Software


There were 2 choices: blog_120608_6

 

MediaPortal

 

 

 

 

blog_120608_7

 

My-HTPC

 

Media Portal, is large well featured and very pretty but it is build for faster machines, on my setup all menus were un-responsive and this kills the application for a jukebox. I chose to use my-HTPC, its a shareware application that ceased in 2003 however it is an excellent front end for media and since I use media player classic for movies and DVD's I don't need these integrated features anyway.  The drawbacks are no support for play-lists and some odd control behaviour and the big one its no-longer in development.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , ,
Categories:   General | Life and Stuff | Projects
Actions:   E-mail | Permalink | Comments (542) | Comment RSSRSS comment feed

Creating Custom Word Menus with Word 2003

Saturday, 26 April 2008 15:00 by frimbob

As part of my office project I have found the need to create a custom menu, it sound easy but it really is not. There exist many cravats which need to be overcome before a menu can be created. In the following post I will attempt to explain how I have archived this.

Note about Application.CustomizationContext Property

MSDN Article Here

From the MSDN Article "Returns or sets a Template or Document object that represents the template or document in which changes to menu bars, toolbars, and key bindings are stored."

Before one can build custom Menus for Word an understanding of CustomizationContext is necessary. All controls for the commandbar have a context to either the current document or the a Template. That being said the default template is 'Normal.dot' . Once a menu is added it is saved into the current context, if you have opened a blank document Normal.dot will have these values saved into them, if you current context is another template that template will receive the new menus.

This applies for both Application and document level customizations.

A word about Persistence.

Word is unlike Excel it will not respect the 'Temporary:=True' parameter of the controls.add() method that is used to build the menus.  Therefore once a menu is created it is persistent for its current context.

For example if I create a menu programmatically and the context is normal.dot then that menu is persistent  in that template and every person using this template will have the same menu, so where is the problem? Our code will run every time the template is loaded a new menu will then be added to the current context, they will not overwrite... so after 10 executions of Word we will have 10 separate menus.

The solution is to find if the menu your about to add exists and if so delete/remove the menu before you add the new menu. I will demonstrate this solution later in this post.

I have asked myself should we delete the menu or just test for its existence, after some thought I arrived at the following conclusion, It is better to remove the menu, if items are added to the menu later a simple test against a menus tag (id name) will not be sufficient. By deleting the menu we ensure an up to date menu.

 

The Code

The is a MSDN article How to: Create Office Menus Programmatically, that covers creating a menu for Excel programmatically. It However does not cover the cravats when creating a menu for Word. You will notice that the code below is very similar to the MSDN Article. Please note , the following line.

 

  71:                 cmdBarControl.Tag = menuTag

 

This line is missing from the MSDN article, and is necessary for the Sub CheckIfMenuExists() to match the menu, this function uses the tag to identify the menu that is why we declare the menuTag at the class level.

   1: Public Class UIcontrols
   2:  
   3: #Region "Declarations"
   4:  
   5:     'Others Removed for Remove for brevity
   6:  
   7:     Private adoc As TheDocument = New TheDocument()
   8:     'menu bar declarations
   9:     Private WithEvents menuCommand As Office.CommandBarButton
  10:     Private menuTag As String = "Air Stories Helper Program"
  11:     Private menuID As Object = "AirStories"
  12:  
  13: #End Region
  14:     
  15: #Region "properties"
  16:     Private thisapp As Word.Application
  17:     Public Property ThisApplication() As Word.Application
  18:         Get
  19:             Return thisapp
  20:         End Get
  21:         Set(ByVal value As Word.Application)
  22:             thisapp = value
  23:         End Set
  24:     End Property
  25: #End Region
  26:     
  27: #Region "Public Methods"
  28:     'loads the controls on the toolbar
  29:     Public Sub LoadControls()
  30:     
  31:     'apply menu bars
  32:         Me.CheckIfMenuBarExists()
  33:         Me.AddMenuBar()
  34:         
  35:     End Sub
  36:     

37: ' If the menu already exists, remove it.

  38:     Private Sub CheckIfMenuBarExists()
  39:         Try
  40:             Dim foundMenu As Office.CommandBarPopup = _
  41:                thisapp.Application.CommandBars.ActiveMenuBar.FindControl( _ 
  42:                Office.MsoControlType.msoControlPopup, Tag:=menuTag, Visible:=True, Recursive:=True)
  43:             If foundMenu IsNot Nothing Then
  44:                 foundMenu.Delete(True)
  45:             End If
  46:  
  47:         Catch ex As Exception
  48:             MessageBox.Show(ex.Message)
  49:         End Try
  50:     End Sub
  51:     
  52:     ' Create the menu,
  53:     Private Sub AddMenuBar()
  54:  
  55:         Try
  56:             Dim menuBar As Office.CommandBar = WordAddIn1.Globals.ThisAddIn.Application. _ 
  57:                                                 CommandBars.ActiveMenuBar
  58:             Dim menuCaption As String = "AIR Menu"
  59:  
  60:             If menuBar IsNot Nothing Then
  61:                 Dim cmdBarControl As Office.CommandBarPopup = Nothing
  62:                 Dim controlCount As Integer = menuBar.Controls.Count
  63:  
  64:                 ' Add the new menu.
  65:                 cmdBarControl = CType(menuBar.Controls.Add(_
  66:                                      Type:=Office.MsoControlType.msoControlPopup, _
  67:                                      Before:=controlCount, Temporary:=True), _
  68:                                      Office.CommandBaPopup)
  69:  
  70:                 cmdBarControl.Caption = menuCaption
  71:                 cmdBarControl.Tag = menuTag
  72:  
  73:  
  74:                 ' Add the menu command.
  75:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  76:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  77:                     Office.CommandBarButton)
  78:  
  79:                 With menuCommand
  80:                     .Caption = "Change Articles Order"
  81:                     .Tag = "Menu item"
  82:                     .FaceId = 300
  83:                 End With
  84:  
  85:                 ' Add the menu command.
  86:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  87:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  88:                     Office.CommandBarButton)
  89:  
  90:                 With menuCommand
  91:                     .Caption = "Process Articles"
  92:                     .Tag = "Menu item"
  93:                     .FaceId = 342
  94:                 End With
  95:  
  96:                 ' Add the menu command.
  97:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  98:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  99:                     Office.CommandBarButton)
 100:  
 101:                 With menuCommand
 102:                     .Caption = "New Document"
 103:                     .Tag = "Menu item"
 104:                     .FaceId = 278
 105:                 End With
 106:  
 107:             End If
 108:  
 109:         Catch ex As Exception
 110:             MessageBox.Show(ex.Message)
 111:         End Try
 112:     End Sub
 113:     
 114:         'Event Handlers Remove for brevity
 115:     
 116: #End Region
 117:  
 118: End Class

 

The Function CheckifMenuExists() is very simple at its heart is the FindControl() method

 

   1: ' If the menu already exists, remove it.
   2:     Private Sub CheckIfMenuBarExists()
   3:         Try
   4:             Dim foundMenu As Office.CommandBarPopup = _
   5:             thisapp.Application.CommandBars.ActiveMenuBar.FindControl(_ 
   6:             Office.MsoControlType.msoControlPopup, Tag:=menuTag, Visible:=True, Recursive:=True)
   7:             If foundMenu IsNot Nothing Then
   8:                 foundMenu.Delete(True)
   9:             End If
  10:  
  11:         Catch ex As Exception
  12:             MessageBox.Show(ex.Message)
  13:         End Try
  14:     End Sub

 

The FindControl() is from the current application namespace , its current commandBars and finally its activemenu. The 2 most important parameters are the Tag and the type. As explained earlier the FindControl() is matched on a type and a tag. After the Findcontrol method is executed it is tested for a null reference (Nothing in VB). The menu is deleted if found.

 

AddMenubar()

   1: Private Sub AddMenuBar()
   2:  
   3:         Try
   4:             Dim menuBar As Office.CommandBar = WordAddIn1.Globals.ThisAddIn.Application.CommandBars.ActiveMenuBar
   5:             Dim menuCaption As String = "AIR Menu"
   6:  
   7:             If menuBar IsNot Nothing Then
   8:                 Dim cmdBarControl As Office.CommandBarPopup = Nothing
   9:                 Dim controlCount As Integer = menuBar.Controls.Count
  10:  
  11:                 ' Add the new menu.
  12:                 cmdBarControl = CType(menuBar.Controls.Add( _
  13:                     Type:=Office.MsoControlType.msoControlPopup, Before:=controlCount, Temporary:=True), _
  14:                     Office.CommandBarPopup)
  15:  
  16:                 cmdBarControl.Caption = menuCaption
  17:                 cmdBarControl.Tag = menuTag
  18:  
  19:         'Code removed for Brevity
  20:  
  21:         Catch ex As Exception
  22:            MessageBox.Show(ex.Message)
  23:        End Try
  24: End Sub

 

The above code will Create and empty menu,  The menuBar declaration is using the application namespace.commandbars.ActiveMenuBar to retrieve the active menubar in the current context.

The cmdBarControl is a CommandBarPopup, which make sense as each menu popsup when click on in the menu bar. It is initially set to null as we will use the 'menuBar Controls.Add()' method to add this control to the menu bar hierarchy.

 

   1: ' Add the new menu.
   2:    cmdBarControl = CType(menuBar.Controls.Add( _
   3:     Type:=Office.MsoControlType.msoControlPopup, Before:=controlCount, Temporary:=True), _
   4:        Office.CommandBarPopup)

 

Since the Controls.Add() method returns a reference to the new control we are doing 2 things in the above code, where adding a CommandBarPopup to the menuBar hierarchy through the Add method and assigning its reference to the cmdBarControl so we can later set its properties.

 

   1: cmdBarControl.Caption = menuCaption
   2: cmdBarControl.Tag = menuTag

 

As mentioned earlier both the above properties must be unique string values.

 

Adding Items to the new menu

Part 2 off the AddMenuBar()

   1: Public Class UIcontrols
   2:  
   3:     'Code Removed for Remove for brevity
   4:  
   5:     ' Create the menu,
   6:     Private Sub AddMenuBar()
   7:     
   8:     'Code Removed for Remove for brevity
   9:  
  10:     ' Add the menu command.
  11:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  12:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  13:                     Office.CommandBarButton)
  14:  
  15:                 With menuCommand
  16:                     .Caption = "Change Articles Order"
  17:                     .Tag = "Menu item"
  18:                     .FaceId = 300
  19:                 End With
  20:  
  21:                 ' Add the menu command.
  22:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  23:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  24:                     Office.CommandBarButton)
  25:  
  26:                 With menuCommand
  27:                     .Caption = "Process Articles"
  28:                     .Tag = "Menu item"
  29:                     .FaceId = 342
  30:                 End With
  31:  
  32:                 ' Add the menu command.
  33:                 menuCommand = CType(cmdBarControl.Controls.Add( _
  34:                     Type:=Office.MsoControlType.msoControlButton, Temporary:=True), _
  35:                     Office.CommandBarButton)
  36:  
  37:                 With menuCommand
  38:                     .Caption = "New Document"
  39:                     .Tag = "Menu item"
  40:                     .FaceId = 278
  41:                 End With
  42:  
  43:             End If
  44:  
  45:         Catch ex As Exception
  46:             MessageBox.Show(ex.Message)
  47:         End Try
  48:     End Sub

 

The following code creates new items on the menu. Areas to not are the FaceId of the menuCommand. The Proeprty sets the icon to use on the menu, A good source of information on that can be found at MSDN FaceID article and a list of numbes to icons can be found here. The Caption is the text that the control displays in the menu, while the tag is the ID of the control. 

It is very important that each Tag be unique for the menu container, Why might you ask? Unfortunately there is only one event for the menu that is the click event on the menuCommand which you would expect, but what you wouldn't expect is the event bubbles. This mentions briefly in the MSDN article where the is based from.  Quote from the Article:-

You must set the Tag property of your controls when you add event handlers. Office uses the Tag property to keep track of event handlers for a specific CommandBarControl. If the Tag property is blank, the events are not handled properly.

An Event Handler like the one below is needed to differentiate between the menu items.

   1: Private Sub menuCommand_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, _
   2:     ByRef CancelDefault As Boolean) Handles menuCommand.Click
   3:  
   4:     'select a action to completet
   5:     Select Case Ctrl.Caption
   6:         Case "New Document"
   7:             'MsgBox("New Document")
   8:             Call Newdocument()
   9:  
  10:         Case "Process Articles"
  11:             'MsgBox("Process Articles")
  12:  
  13:         Case "Change Articles Order"
  14:             'MsgBox("Change Articles Order")
  15:  
  16:         Case Else
  17:             Throw New Exception("Menu Error")
  18:  
  19:     End Select
  20:  
  21: End Sub

 

This causes problems when you wish to use the same event handler for the toolbar buttons and the menu buttons. I found that I had to move the event code into functions and subs that could be called from both event-handlers, There may be another solution that presents itself with more time and research invested but not at the current time.

 

The Result

blog_260408_01

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   , , ,
Categories:   Projects
Actions:   E-mail | Permalink | Comments (580) | Comment RSSRSS comment feed