diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bc915c --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/AddIns/AddIn.Common/AddIn.Common.csproj b/AddIns/AddIn.Common/AddIn.Common.csproj new file mode 100644 index 0000000..8d5aef2 --- /dev/null +++ b/AddIns/AddIn.Common/AddIn.Common.csproj @@ -0,0 +1,65 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {D32C4454-9334-47AA-9A3F-456B8B12220A} + Library + Properties + Foo.AddIn.Common + Foo.AddIn.Common + v3.5 + 512 + + + true + full + false + ..\..\Target\Debug\AddIns\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Target\Release\AddIns\ + TRACE + prompt + 4 + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AddIns/AddIn.Common/CommonFunctions.cs b/AddIns/AddIn.Common/CommonFunctions.cs new file mode 100644 index 0000000..415b7eb --- /dev/null +++ b/AddIns/AddIn.Common/CommonFunctions.cs @@ -0,0 +1,399 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices.ComTypes; +using System.Runtime.InteropServices; +using System.Drawing; +using System.Diagnostics; + +namespace Foo.AddIn.Common +{ + #region Structs + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + + public Rectangle AsRectangle + { + get + { + return new Rectangle(this.left, this.top, this.right - this.left, this.bottom - this.top); + } + } + + public static RECT FromXYWH(int x, int y, int width, int height) + { + RECT rect = new RECT(); + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + return rect; + } + + public static RECT FromRectangle(Rectangle rectangle) + { + RECT rect = new RECT(); + rect.left = rectangle.Left; + rect.top = rectangle.Top; + rect.right = rectangle.Right; + rect.bottom = rectangle.Bottom; + return rect; + } + } + + #endregion + + public static class Functions + { + #region Enums + + public static class FuncEnum + { + public enum WindowAction : int + { + SW_HIDE = 0, + SW_SHOWNORMAL = 1, + SW_NORMAL = 1, + SW_SHOWMINIMIZED = 2, + SW_SHOWMAXIMIZED = 3, + SW_MAXIMIZE = 3, + SW_SHOWNOACTIVATE = 4, + SW_SHOW = 5, + SW_MINIMIZE = 6, + SW_SHOWMINNOACTIVE = 7, + SW_SHOWNA = 8, + SW_RESTORE = 9, + SW_SHOWDEFAULT = 10, + SW_FORCEMINIMIZE = 11, + SW_MAX = 11 + } + + public enum WindowMessage : int + { + WM_NULL = 0x0000, + WM_CREATE = 0x0001, + WM_DESTROY = 0x0002, + WM_MOVE = 0x0003, + WM_SIZE = 0x0005, + WM_ACTIVATE = 0x0006, + WM_SETFOCUS = 0x0007, + WM_KILLFOCUS = 0x0008, + WM_ENABLE = 0x000A, + WM_SETREDRAW = 0x000B, + WM_SETTEXT = 0x000C, + WM_GETTEXT = 0x000D, + WM_GETTEXTLENGTH = 0x000E, + WM_PAINT = 0x000F, + WM_CLOSE = 0x0010, + WM_QUERYENDSESSION = 0x0011, + WM_QUIT = 0x0012, + WM_QUERYOPEN = 0x0013, + WM_ERASEBKGND = 0x0014, + WM_SYSCOLORCHANGE = 0x0015, + WM_ENDSESSION = 0x0016, + WM_SHOWWINDOW = 0x0018, + WM_CTLCOLOR = 0x0019, + WM_WININICHANGE = 0x001A, + WM_SETTINGCHANGE = 0x001A, + WM_DEVMODECHANGE = 0x001B, + WM_ACTIVATEAPP = 0x001C, + WM_FONTCHANGE = 0x001D, + WM_TIMECHANGE = 0x001E, + WM_CANCELMODE = 0x001F, + WM_SETCURSOR = 0x0020, + WM_MOUSEACTIVATE = 0x0021, + WM_CHILDACTIVATE = 0x0022, + WM_QUEUESYNC = 0x0023, + WM_GETMINMAXINFO = 0x0024, + WM_PAINTICON = 0x0026, + WM_ICONERASEBKGND = 0x0027, + WM_NEXTDLGCTL = 0x0028, + WM_SPOOLERSTATUS = 0x002A, + WM_DRAWITEM = 0x002B, + WM_MEASUREITEM = 0x002C, + WM_DELETEITEM = 0x002D, + WM_VKEYTOITEM = 0x002E, + WM_CHARTOITEM = 0x002F, + WM_SETFONT = 0x0030, + WM_GETFONT = 0x0031, + WM_SETHOTKEY = 0x0032, + WM_GETHOTKEY = 0x0033, + WM_QUERYDRAGICON = 0x0037, + WM_COMPAREITEM = 0x0039, + WM_GETOBJECT = 0x003D, + WM_COMPACTING = 0x0041, + WM_COMMNOTIFY = 0x0044, + WM_WINDOWPOSCHANGING = 0x0046, + WM_WINDOWPOSCHANGED = 0x0047, + WM_POWER = 0x0048, + WM_COPYDATA = 0x004A, + WM_CANCELJOURNAL = 0x004B, + WM_NOTIFY = 0x004E, + WM_INPUTLANGCHANGEREQUEST = 0x0050, + WM_INPUTLANGCHANGE = 0x0051, + WM_TCARD = 0x0052, + WM_HELP = 0x0053, + WM_USERCHANGED = 0x0054, + WM_NOTIFYFORMAT = 0x0055, + WM_CONTEXTMENU = 0x007B, + WM_STYLECHANGING = 0x007C, + WM_STYLECHANGED = 0x007D, + WM_DISPLAYCHANGE = 0x007E, + WM_GETICON = 0x007F, + WM_SETICON = 0x0080, + WM_NCCREATE = 0x0081, + WM_NCDESTROY = 0x0082, + WM_NCCALCSIZE = 0x0083, + WM_NCHITTEST = 0x0084, + WM_NCPAINT = 0x0085, + WM_NCACTIVATE = 0x0086, + WM_GETDLGCODE = 0x0087, + WM_SYNCPAINT = 0x0088, + WM_NCMOUSEMOVE = 0x00A0, + WM_NCLBUTTONDOWN = 0x00A1, + WM_NCLBUTTONUP = 0x00A2, + WM_NCLBUTTONDBLCLK = 0x00A3, + WM_NCRBUTTONDOWN = 0x00A4, + WM_NCRBUTTONUP = 0x00A5, + WM_NCRBUTTONDBLCLK = 0x00A6, + WM_NCMBUTTONDOWN = 0x00A7, + WM_NCMBUTTONUP = 0x00A8, + WM_NCMBUTTONDBLCLK = 0x00A9, + WM_KEYDOWN = 0x0100, + WM_KEYUP = 0x0101, + WM_CHAR = 0x0102, + WM_DEADCHAR = 0x0103, + WM_SYSKEYDOWN = 0x0104, + WM_SYSKEYUP = 0x0105, + WM_SYSCHAR = 0x0106, + WM_SYSDEADCHAR = 0x0107, + WM_KEYLAST = 0x0108, + WM_IME_STARTCOMPOSITION = 0x010D, + WM_IME_ENDCOMPOSITION = 0x010E, + WM_IME_COMPOSITION = 0x010F, + WM_IME_KEYLAST = 0x010F, + WM_INITDIALOG = 0x0110, + WM_COMMAND = 0x0111, + WM_SYSCOMMAND = 0x0112, + WM_TIMER = 0x0113, + WM_HSCROLL = 0x0114, + WM_VSCROLL = 0x0115, + WM_INITMENU = 0x0116, + WM_INITMENUPOPUP = 0x0117, + WM_MENUSELECT = 0x011F, + WM_MENUCHAR = 0x0120, + WM_ENTERIDLE = 0x0121, + WM_MENURBUTTONUP = 0x0122, + WM_MENUDRAG = 0x0123, + WM_MENUGETOBJECT = 0x0124, + WM_UNINITMENUPOPUP = 0x0125, + WM_MENUCOMMAND = 0x0126, + WM_CTLCOLORMSGBOX = 0x0132, + WM_CTLCOLOREDIT = 0x0133, + WM_CTLCOLORLISTBOX = 0x0134, + WM_CTLCOLORBTN = 0x0135, + WM_CTLCOLORDLG = 0x0136, + WM_CTLCOLORSCROLLBAR = 0x0137, + WM_CTLCOLORSTATIC = 0x0138, + WM_MOUSEMOVE = 0x0200, + WM_LBUTTONDOWN = 0x0201, + WM_LBUTTONUP = 0x0202, + WM_LBUTTONDBLCLK = 0x0203, + WM_RBUTTONDOWN = 0x0204, + WM_RBUTTONUP = 0x0205, + WM_RBUTTONDBLCLK = 0x0206, + WM_MBUTTONDOWN = 0x0207, + WM_MBUTTONUP = 0x0208, + WM_MBUTTONDBLCLK = 0x0209, + WM_MOUSEWHEEL = 0x020A, + WM_PARENTNOTIFY = 0x0210, + WM_ENTERMENULOOP = 0x0211, + WM_EXITMENULOOP = 0x0212, + WM_NEXTMENU = 0x0213, + WM_SIZING = 0x0214, + WM_CAPTURECHANGED = 0x0215, + WM_MOVING = 0x0216, + WM_DEVICECHANGE = 0x0219, + WM_MDICREATE = 0x0220, + WM_MDIDESTROY = 0x0221, + WM_MDIACTIVATE = 0x0222, + WM_MDIRESTORE = 0x0223, + WM_MDINEXT = 0x0224, + WM_MDIMAXIMIZE = 0x0225, + WM_MDITILE = 0x0226, + WM_MDICASCADE = 0x0227, + WM_MDIICONARRANGE = 0x0228, + WM_MDIGETACTIVE = 0x0229, + WM_MDISETMENU = 0x0230, + WM_ENTERSIZEMOVE = 0x0231, + WM_EXITSIZEMOVE = 0x0232, + WM_DROPFILES = 0x0233, + WM_MDIREFRESHMENU = 0x0234, + WM_IME_SETCONTEXT = 0x0281, + WM_IME_NOTIFY = 0x0282, + WM_IME_CONTROL = 0x0283, + WM_IME_COMPOSITIONFULL = 0x0284, + WM_IME_SELECT = 0x0285, + WM_IME_CHAR = 0x0286, + WM_IME_REQUEST = 0x0288, + WM_IME_KEYDOWN = 0x0290, + WM_IME_KEYUP = 0x0291, + WM_MOUSEHOVER = 0x02A1, + WM_MOUSELEAVE = 0x02A3, + WM_CUT = 0x0300, + WM_COPY = 0x0301, + WM_PASTE = 0x0302, + WM_CLEAR = 0x0303, + WM_UNDO = 0x0304, + WM_RENDERFORMAT = 0x0305, + WM_RENDERALLFORMATS = 0x0306, + WM_DESTROYCLIPBOARD = 0x0307, + WM_DRAWCLIPBOARD = 0x0308, + WM_PAINTCLIPBOARD = 0x0309, + WM_VSCROLLCLIPBOARD = 0x030A, + WM_SIZECLIPBOARD = 0x030B, + WM_ASKCBFORMATNAME = 0x030C, + WM_CHANGECBCHAIN = 0x030D, + WM_HSCROLLCLIPBOARD = 0x030E, + WM_QUERYNEWPALETTE = 0x030F, + WM_PALETTEISCHANGING = 0x0310, + WM_PALETTECHANGED = 0x0311, + WM_HOTKEY = 0x0312, + WM_PRINT = 0x0317, + WM_PRINTCLIENT = 0x0318, + WM_HANDHELDFIRST = 0x0358, + WM_HANDHELDLAST = 0x035F, + WM_AFXFIRST = 0x0360, + WM_AFXLAST = 0x037F, + WM_PENWINFIRST = 0x0380, + WM_PENWINLAST = 0x038F, + WM_APP = 0x8000, + WM_USER = 0x0400, + WM_REFLECT = WM_USER + 0x1c00, + WM_CHANGEUISTATE = 0x0127, + WM_UPDATEUISTATE = 0x0128, + WM_QUERYUISTATE = 0x0129 + } + } + + #endregion + + #region DLLImports + + [DllImport("ole32.dll")] + public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); + + [DllImport("user32.dll")] + extern public static bool GetWindowRect(IntPtr hWnd, out RECT rect); + + [DllImport("user32.dll")] + extern public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); + + [DllImport("User32.dll")] + extern public static bool IsWindow(IntPtr hwnd); + + [DllImport("User32.dll")] + extern public static bool IsWindowVisible(IntPtr hwnd); + + [DllImport("user32.dll")] + extern public static int ShowWindow(IntPtr hwnd, FuncEnum.WindowAction nCmdShow); + + [DllImport("User32.dll")] + extern public static int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId); + + [DllImport("User32.dll")] + extern public static int SendMessage(IntPtr hWnd, FuncEnum.WindowMessage Msg, IntPtr wParam, IntPtr lParam); + + #endregion + + #region Functions + + /// + /// Returns the .Net Process Object that owns the passed in hWnd + /// + public static Process GetProcessFromHandle(IntPtr hWnd) + { + int currentPid = 0; + GetWindowThreadProcessId(hWnd, ref currentPid); + + Process process; + process = Process.GetProcessById(currentPid); + return process; + } + + /// + /// Attaches to instance of COM object matching progid + /// and returns an object. Client must cast and know + /// expected type. + /// + public static Object GetCOMObject(string progId) + { + Object app = null; + try + { + app = Marshal.GetActiveObject(progId); + } + catch (SystemException) { /* ignore */ } + return app; + } + + /// + /// Use this to Get A specific type of Object from the ROT + /// + public static List GetRunningObjectsOfType() + { + // Get the table. + var res = new List(); + IBindCtx bc; + + CreateBindCtx(0, out bc); + IRunningObjectTable runningObjectTable; + + bc.GetRunningObjectTable(out runningObjectTable); + IEnumMoniker monikerEnumerator; + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + // Enumerate and fill our nice dictionary. + IMoniker[] monikers = new IMoniker[1]; + IntPtr numFetched = IntPtr.Zero; + + while (monikerEnumerator.Next(1, monikers, numFetched) == 0) + { + object o; + runningObjectTable.GetObject(monikers[0], out o); + + if (o is T) + { + res.Add((T)o); + } + o = null; + } + return res; + } + + /// + /// Get a windows rectangle in a .NET structure + /// + /// The window handle to look up + /// The rectangle + public static Rectangle GetWindowRect(IntPtr hwnd) + { + RECT rect = new RECT(); + GetWindowRect(hwnd, out rect); + return rect.AsRectangle; + } + + #endregion + } + + +} diff --git a/AddIns/AddIn.Common/CommonTypes.cs b/AddIns/AddIn.Common/CommonTypes.cs new file mode 100644 index 0000000..a7338f9 --- /dev/null +++ b/AddIns/AddIn.Common/CommonTypes.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.AddIn.Common +{ + /// + /// Common Return Value for Addins + /// + public class FuncRetVal + { + public FuncRetValEnum Type { get; set; } + public string Message { get; set; } + } + + /// + /// Useful for Returns where we + /// need more information on failures + /// + public enum FuncRetValEnum + { + Action_Succeeded, + Action_Failed, + NoAction_Needed, + ParameterInvalid, + ArtifactUnavailable, + FunctionallityNotSupported, + ErrorThrown + } +} diff --git a/AddIns/AddIn.Common/CommonValidations.cs b/AddIns/AddIn.Common/CommonValidations.cs new file mode 100644 index 0000000..48ad9e1 --- /dev/null +++ b/AddIns/AddIn.Common/CommonValidations.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace Foo.AddIn.Common +{ + public static class Validate + { + /// + /// Validate ArtifactLocation * We could later do much more work here * + /// + /// + public static bool IsValidArtifactLocation(string strArtifactLocation, ref FuncRetVal retVal) + { + // All URLs should contain that character (Files aren't allowed to contain it) + bool bIsUrl = strArtifactLocation.Contains('/'); + + if (String.IsNullOrEmpty(strArtifactLocation)) + { + retVal.Type = FuncRetValEnum.ParameterInvalid; + return false; + } + else if (!bIsUrl && !File.Exists(strArtifactLocation)) + { + // Check File existence (if it doesn't return false) + return false; + } + else + { + return true; + } + } + + } +} diff --git a/AddIns/AddIn.Common/IAddIn.cs b/AddIns/AddIn.Common/IAddIn.cs new file mode 100644 index 0000000..d11504d --- /dev/null +++ b/AddIns/AddIn.Common/IAddIn.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.AddIn.Common +{ + public interface IAddIn + { + // I + + + } +} diff --git a/AddIns/AddIn.Common/IDynResolve.cs b/AddIns/AddIn.Common/IDynResolve.cs new file mode 100644 index 0000000..b045e82 --- /dev/null +++ b/AddIns/AddIn.Common/IDynResolve.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.AddIn.Common +{ + public interface IDynResolve + { + // I + + + } +} diff --git a/AddIns/AddIn.Common/IWorkspace.cs b/AddIns/AddIn.Common/IWorkspace.cs new file mode 100644 index 0000000..53b75ac --- /dev/null +++ b/AddIns/AddIn.Common/IWorkspace.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.AddIn.Common +{ + public interface IWorkspace + { + // Launchers + FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft); + FuncRetVal Launch(string strArtifactLocation); + + // ShowNHiders + FuncRetVal Show(string strArtifactLocation); + FuncRetVal Hide(string strArtifactLocation); + + // Closers + FuncRetVal QueryClose(string strArtifactLocation); + FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft); + FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact); + FuncRetVal Close(string strArtifactLocation); + } +} diff --git a/AddIns/AddIn.Common/Properties/AssemblyInfo.cs b/AddIns/AddIn.Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..166cc13 --- /dev/null +++ b/AddIns/AddIn.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("AddIn.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("AddIn.Common")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("39d7351f-149f-4d32-a3ae-d07ec27515af")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/AddIns/Addin.Office/Access.cs b/AddIns/Addin.Office/Access.cs new file mode 100644 index 0000000..b0ce159 --- /dev/null +++ b/AddIns/Addin.Office/Access.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Drawing; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class Access_Workspace : IWorkspace + { + public const string Access_ProgId = "Access.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Access.Application app = new Microsoft.Office.Interop.Access.Application(); + app.Visible = true; + + // Must test the following here: + // - open both .mdb and .adp (access project files with this) + // - how does this behave when db is password protected? + app.OpenCurrentDatabase(strArtifactLocation, true, ""); + + // ToDo: Check if a new process got created? / or if hWnd exists??? + // - Also PERFORM Window Positioning + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Access.Application app = new Microsoft.Office.Interop.Access.Application(); + app.Visible = true; + + // Must test the following here: + // - open both .mdb and .adp (access project files with this) + // - how does this behave when db is password protected? + app.OpenCurrentDatabase(strArtifactLocation, true, ""); + + // ToDo: Check if a new process got created? / or if hWnd exists??? + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + IntPtr hWnd = (IntPtr)app.hWndAccessApp(); + if (!Functions.IsWindowVisible(hWnd)) + { + Functions.ShowWindow(hWnd, Functions.FuncEnum.WindowAction.SW_SHOW); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + IntPtr hWnd = (IntPtr)app.hWndAccessApp(); + if (Functions.IsWindowVisible(hWnd)) + { + Functions.ShowWindow(hWnd, Functions.FuncEnum.WindowAction.SW_HIDE); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + IntPtr hWnd = (IntPtr) app.hWndAccessApp(); + if (Functions.SendMessage(hWnd, Functions.FuncEnum.WindowMessage.WM_QUERYENDSESSION, IntPtr.Zero, IntPtr.Zero) != 0) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get Handle and Process + IntPtr hWnd = (IntPtr)app.hWndAccessApp(); + Process process = Functions.GetProcessFromHandle((IntPtr)hWnd); + + // Get the Window properties + Rectangle rect = Functions.GetWindowRect(hWnd); + WindowHeight = rect.Height; + WindowWidth = rect.Width; + WindowLeft = rect.Left; + WindowTop = rect.Top; + + // Close the database + //app.CloseCurrentDatabase(); + if (bAutoSaveArtifact) + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll); + else + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone); + Marshal.FinalReleaseComObject(app); // force clean-up + + // Kill the process + process.Kill(); + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get Handle and Process + IntPtr hWnd = (IntPtr)app.hWndAccessApp(); + Process process = Functions.GetProcessFromHandle((IntPtr)hWnd); + + // Close the database + //app.CloseCurrentDatabase(); + if(bAutoSaveArtifact) + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll); + else + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone); + Marshal.FinalReleaseComObject(app); // force clean-up + + // Kill the process + process.Kill(); + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningAccessApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get Handle and Process + IntPtr hWnd = (IntPtr)app.hWndAccessApp(); + Process process = Functions.GetProcessFromHandle((IntPtr)hWnd); + + // Close the database + //app.CloseCurrentDatabase(); + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll); + Marshal.FinalReleaseComObject(app); // force clean-up + + // Kill the process + process.Kill(); + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/AddIns/Addin.Office/AddIn.cs b/AddIns/Addin.Office/AddIn.cs new file mode 100644 index 0000000..7f834bd --- /dev/null +++ b/AddIns/Addin.Office/AddIn.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; + +namespace Foo.Addin.Office +{ + public class AddIn : IAddIn + { + + } +} diff --git a/AddIns/Addin.Office/Addin.Office.csproj b/AddIns/Addin.Office/Addin.Office.csproj new file mode 100644 index 0000000..83e97bc --- /dev/null +++ b/AddIns/Addin.Office/Addin.Office.csproj @@ -0,0 +1,106 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {0CA1DD2E-2752-4587-ADB4-77194411648B} + Library + Properties + Foo.Addin.Office + Foo.Addin.Office + v3.5 + 512 + + + true + full + false + ..\..\Target\Debug\AddIns\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Target\Release\AddIns\ + TRACE + prompt + 4 + + + + False + False + + + False + False + + + False + False + + + False + False + + + False + False + + + False + False + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + {D32C4454-9334-47AA-9A3F-456B8B12220A} + AddIn.Common + + + + + {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52} + 2 + 3 + 0 + primary + False + + + + + \ No newline at end of file diff --git a/AddIns/Addin.Office/Excel.cs b/AddIns/Addin.Office/Excel.cs new file mode 100644 index 0000000..5d003e3 --- /dev/null +++ b/AddIns/Addin.Office/Excel.cs @@ -0,0 +1,383 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Reflection; + +using Foo.AddIn.Common; +using System.Drawing; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class Excel_Workspace : IWorkspace + { + public const string Excel_ProgId = "Excel.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Excel.Application app = null; + app = new Microsoft.Office.Interop.Excel.Application(); + + // Mark the Application as visible + app.Visible = true; + + // Position the Window + IntPtr hWnd = (IntPtr)app.Hwnd; + Functions.SetWindowPos(hWnd, IntPtr.Zero, WindowLeft, WindowTop, WindowHeight, WindowWidth, 0); + + // Open/Load the Document + Microsoft.Office.Interop.Excel.Workbook workbook = app.Workbooks.Open(strArtifactLocation, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); + if (workbook != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Excel.Application app = null; + app = new Microsoft.Office.Interop.Excel.Application(); + + // Mark the Application as visible + app.Visible = true; + + Microsoft.Office.Interop.Excel.Workbook workbook = app.Workbooks.Open(strArtifactLocation, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); + if (workbook != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + + // If For some reason the App is visible + if (app.Visible) + { + // Make Sure that this Workbook is activated + if (!bIsTheOnlyDocumentInApp) + { + book.Activate(); + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + } + return retVal; + } + + app.Visible = true; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + + if (!app.Visible) + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + + // If this is NOT the Only open workbook in this App + // ~Activate the other workbook + if (!bIsTheOnlyDocumentInApp) + { + foreach (Microsoft.Office.Interop.Excel.Workbook book2 in app.Workbooks) + { + if (book2.FullName.ToLower() != strArtifactLocation.ToLower()) + { + book2.Activate(); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + } + else + { + app.Visible = false; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (book.Saved) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // In case there is a running rogue excel process left open, + // we can always force it to close by closing the process + // int hWnd = app.Hwnd; + // Process process = Win32Functions.GetProcessFromHandle((IntPtr) hWnd); + var app = book.Application; + + // Get the Window properties + IntPtr hWnd = (IntPtr)app.Hwnd; + Rectangle rect = Functions.GetWindowRect(hWnd); + WindowHeight = rect.Height; + WindowWidth = rect.Width; + WindowLeft = rect.Left; + WindowTop = rect.Top; + + // Close the Workbook + book.Close(bAutoSaveArtifact, strArtifactLocation, false); + Marshal.FinalReleaseComObject(book); // force clean-up + + // Close Excel if this is the last Workbook + if (app.Workbooks.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, should clean up excel process + //process.Close(); + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // In case there is a running rogue excel process left open, + // we can always force it to close by closing the process + // int hWnd = app.Hwnd; + // Process process = Win32Functions.GetProcessFromHandle((IntPtr) hWnd); + var app = book.Application; + + // Close the Workbook + book.Close(bAutoSaveArtifact, strArtifactLocation, false); + Marshal.FinalReleaseComObject(book); // force clean-up + + // Close Excel if this is the last Workbook + if (app.Workbooks.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, should clean up excel process + //process.Close(); + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningExcelWorkbooks = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // In case there is a running rogue excel process left open, + // we can always force it to close by closing the process + // int hWnd = app.Hwnd; + // Process process = Win32Functions.GetProcessFromHandle((IntPtr) hWnd); + var app = book.Application; + + // Close the Workbook + book.Close(true, strArtifactLocation, false); + Marshal.FinalReleaseComObject(book); // force clean-up + + // Close Excel if this is the last Workbook + if (app.Workbooks.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, should clean up excel process + //process.Close(); + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/AddIns/Addin.Office/PowerPoint.cs b/AddIns/Addin.Office/PowerPoint.cs new file mode 100644 index 0000000..6cd41af --- /dev/null +++ b/AddIns/Addin.Office/PowerPoint.cs @@ -0,0 +1,379 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; +using System.Runtime.InteropServices; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class PowerPoint_Workspace : IWorkspace + { + public const string PowerPoint_ProgId = "PowerPoint.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.PowerPoint.Application app = null; + app = Functions.GetCOMObject(PowerPoint_ProgId) as Microsoft.Office.Interop.PowerPoint.Application; + + // If no existing PowerPoint App is open, open a new one + if (app == null) + { + app = new Microsoft.Office.Interop.PowerPoint.Application(); + app.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; + } + + // If there is an existing presentation, don't position the window + bool bThereIsAnExistingPresentation = (app.Presentations.Count > 0); + + // Open the PowerPoint Presentation + Microsoft.Office.Interop.PowerPoint.Presentation presentation = null; + presentation = app.Presentations.Open(strArtifactLocation, Microsoft.Office.Core.MsoTriState.msoFalse, + Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue); + + if (presentation != null) + { + // Position the Window + if (!bThereIsAnExistingPresentation) + { + IntPtr hWnd = (IntPtr) app.HWND; + Functions.SetWindowPos(hWnd, IntPtr.Zero, WindowLeft, WindowTop, WindowHeight, WindowWidth, 0); + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.PowerPoint.Application app = null; + app = Functions.GetCOMObject(PowerPoint_ProgId) as Microsoft.Office.Interop.PowerPoint.Application; + + // If no existing PowerPoint App is open, open a new one + if (app == null) + { + app = new Microsoft.Office.Interop.PowerPoint.Application(); + app.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; + } + + // Open the PowerPoint Presentation + Microsoft.Office.Interop.PowerPoint.Presentation presentation = null; + presentation = app.Presentations.Open(strArtifactLocation, Microsoft.Office.Core.MsoTriState.msoFalse, + Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue); + + if (presentation != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + + case Microsoft.Office.Core.MsoTriState.msoFalse: + { + presentation.Application.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; + + //Functions.ShowWindow((IntPtr)presentation.Application.HWND, (int)Functions.WindowAction.SW_SHOW); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + { + presentation.Application.Visible = Microsoft.Office.Core.MsoTriState.msoFalse; + + //Functions.ShowWindow((IntPtr)presentation.Application.HWND, (int)Functions.WindowAction.SW_HIDE); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + + case Microsoft.Office.Core.MsoTriState.msoFalse: + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Saved) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + + case Microsoft.Office.Core.MsoTriState.msoFalse: + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = presentation.Application; + + // Save this Presentation + if (bAutoSaveArtifact) + presentation.Save(); + + // Pass out the Window Information + WindowTop = (int) presentation.Application.Top; + WindowLeft = (int) presentation.Application.Left; + WindowHeight = (int) presentation.Application.Height; + WindowWidth = (int)presentation.Application.Width; + + // Close this Presentation + presentation.Close(); + + Marshal.FinalReleaseComObject(presentation); // force clean-up + + // Close PowerPoint if there are no more Presentations + if (app.Presentations.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, kill application for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = presentation.Application; + + // Save this Presentation + if(bAutoSaveArtifact) + presentation.Save(); + + // Close this Presentation + presentation.Close(); + + Marshal.FinalReleaseComObject(presentation); // force clean-up + + // Close PowerPoint if there are no more Presentations + if (app.Presentations.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, kill application for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPowerPoints = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = presentation.Application; + + // Save this Presentation + presentation.Save(); + + // Close this Presentation + presentation.Close(); + + Marshal.FinalReleaseComObject(presentation); // force clean-up + + // Close PowerPoint if there are no more Presentations + if (app.Presentations.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, kill application for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/AddIns/Addin.Office/Properties/AssemblyInfo.cs b/AddIns/Addin.Office/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7a95a77 --- /dev/null +++ b/AddIns/Addin.Office/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Addin.Office")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Addin.Office")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("79a22796-d344-456e-90a3-9e28c0f31d31")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/AddIns/Addin.Office/Publisher.cs b/AddIns/Addin.Office/Publisher.cs new file mode 100644 index 0000000..ed0abbc --- /dev/null +++ b/AddIns/Addin.Office/Publisher.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; +using System.Diagnostics; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class Publisher_Workspace : IWorkspace + { + public const string Publisher_ProgId = "Publisher.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Publisher.Application app = new Microsoft.Office.Interop.Publisher.Application(); + + // Opens Publisher + Microsoft.Office.Interop.Publisher.Document doc = null; + doc = app.Open(strArtifactLocation, false, false, Microsoft.Office.Interop.Publisher.PbSaveOptions.pbSaveChanges); + + // Position the Window + IntPtr hWnd = (IntPtr)doc.ActiveWindow.Hwnd; + Functions.SetWindowPos(hWnd, IntPtr.Zero, WindowLeft, WindowTop, WindowHeight, WindowWidth, 0); + + if (doc != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Publisher.Application app = new Microsoft.Office.Interop.Publisher.Application(); + + // Opens Publisher + Microsoft.Office.Interop.Publisher.Document doc = null; + doc = app.Open(strArtifactLocation, false, false, Microsoft.Office.Interop.Publisher.PbSaveOptions.pbSaveChanges); + + if (doc != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + + if (pubDoc.ActiveWindow.Visible) + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + else + { + pubDoc.ActiveWindow.Visible = true; + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + + if (!pubDoc.ActiveWindow.Visible) + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + else + { + pubDoc.ActiveWindow.Visible = false; + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (pubDoc.Saved) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + if (bAutoSaveArtifact) + pubDoc.Save(); + + // Get the Window properties + WindowTop = pubDoc.ActiveWindow.Top; + WindowLeft = pubDoc.ActiveWindow.Left; + WindowWidth = pubDoc.ActiveWindow.Width; + WindowHeight = pubDoc.ActiveWindow.Height; + + // Get the Handle + IntPtr hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + Process process = Functions.GetProcessFromHandle(hWnd); + + // Send Close Message + if (Functions.SendMessage((IntPtr)hWnd, Functions.FuncEnum.WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + { + process.Kill(); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + if(bAutoSaveArtifact) + pubDoc.Save(); + + // Get the Handle + IntPtr hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + Process process = Functions.GetProcessFromHandle(hWnd); + + // Send Close Message + if (Functions.SendMessage((IntPtr)hWnd, Functions.FuncEnum.WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + { + process.Kill(); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningPublisherApps = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + pubDoc.Save(); + + // Get the Handle + IntPtr hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + Process process = Functions.GetProcessFromHandle(hWnd); + + // Send Close Message + if (Functions.SendMessage((IntPtr)hWnd, Functions.FuncEnum.WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + { + process.Kill(); + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/AddIns/Addin.Office/Visio.cs b/AddIns/Addin.Office/Visio.cs new file mode 100644 index 0000000..1275022 --- /dev/null +++ b/AddIns/Addin.Office/Visio.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; +using System.Runtime.InteropServices; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class Visio_Workspace : IWorkspace + { + public const string Visio_ProgId = "Visio.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Visio.Application app = null; + app = new Microsoft.Office.Interop.Visio.Application(); + + // Mark the Application as visible + app.Visible = true; + + app.Documents.Open(strArtifactLocation); + + // ToDo: Check if a new process got created? / or if hWnd exists??? + // - Also PERFORM Window Positioning + app.ActiveWindow.SetWindowRect(WindowLeft, WindowTop, WindowWidth, WindowHeight); + + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + + Microsoft.Office.Interop.Visio.Application app = null; + app = new Microsoft.Office.Interop.Visio.Application(); + + // Mark the Application as visible + app.Visible = true; + + app.Documents.Open(strArtifactLocation); + + // Keep Track of all our Excel Instances -- not needed in visio? + ///WorkspaceState.Launched_ExcelInstances.Add(app); + + retVal.Type = FuncRetValEnum.Action_Succeeded; + + //if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + //{ + // Process.Start(strArtifactLocation); + //} + //return FuncDepBoolType.ParametersInvalid; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // TO DO - (doc.Application.Documents.Count == 1); not working, why?!?!? odd + bool bIsTrue = (doc.Application.Documents.Count == 1); // not working, why?!?!? odd + //bool bIsTheOnlyDocumentInApp = true; + + if (!doc.Application.Visible) // && bIsTheOnlyDocumentInApp) + { + doc.Application.Visible = true; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // TO DO - (doc.Application.Documents.Count == 1); not working, why?!?!? odd + bool bIsTrue = (doc.Application.Documents.Count == 1); // not working, why?!?!? odd + //bool bIsTheOnlyDocumentInApp = true; + + if (doc.Application.Visible) // && bIsTheOnlyDocumentInApp) + { + doc.Application.Visible = false; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (doc.Saved) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (bAutoSaveArtifact) + doc.Save(); + + var app = doc.Application; + + // Get the Window properties + app.ActiveWindow.GetWindowRect(out WindowLeft, out WindowTop, out WindowWidth, out WindowHeight); + + doc.Close(); + Marshal.FinalReleaseComObject(doc); // Force Clean-up + + if (app.Documents.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if(bAutoSaveArtifact) + doc.Save(); + + var app = doc.Application; + + doc.Close(); + Marshal.FinalReleaseComObject(doc); // Force Clean-up + + if (app.Documents.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningVisioDocs = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + doc.Save(); + + var app = doc.Application; + + doc.Close(); + Marshal.FinalReleaseComObject(doc); // Force Clean-up + + if (app.Documents.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/AddIns/Addin.Office/Word.cs b/AddIns/Addin.Office/Word.cs new file mode 100644 index 0000000..b5ab8de --- /dev/null +++ b/AddIns/Addin.Office/Word.cs @@ -0,0 +1,424 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.AddIn.Common; +using System.Runtime.InteropServices; +using System.Reflection; + +// Ignore 'Ambiguity' warning message, seems like no way around those +#pragma warning disable 0467 + +namespace Foo.Addin.Office +{ + public class Word_Workspace : IWorkspace + { + public const string Word_ProgId = "Word.Application"; + + public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Word.Application app = null; + app = Functions.GetCOMObject(Word_ProgId) as Microsoft.Office.Interop.Word.Application; + + // If no existing Word App is open, open a new one + if (app == null) + { + app = new Microsoft.Office.Interop.Word.Application(); + app.Visible = true; + } + + object fileName = strArtifactLocation; + object missing = Missing.Value; + Microsoft.Office.Interop.Word.Document doc = null; + doc = app.Documents.Open(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, + ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); + + if (doc != null) + { + // Find the correct Window and position it + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + window.Top = WindowTop; + window.Left = WindowLeft; + window.Height = WindowHeight; + window.Width = WindowWidth; + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Launch(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + Microsoft.Office.Interop.Word.Application app = null; + app = Functions.GetCOMObject(Word_ProgId) as Microsoft.Office.Interop.Word.Application; + + // If no existing Word App is open, open a new one + if (app == null) + { + app = new Microsoft.Office.Interop.Word.Application(); + app.Visible = true; + } + + object fileName = strArtifactLocation; + object missing = Missing.Value; + Microsoft.Office.Interop.Word.Document doc = null; + doc = app.Documents.Open(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, + ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); + + if (doc != null) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + } + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Show(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (!window.Visible) + { + window.Visible = true; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Hide(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (window.Visible) + { + window.Visible = false; + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.NoAction_Needed; + return retVal; + } + } + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal QueryClose(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (doc.Saved) + { + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + else + { + retVal.Type = FuncRetValEnum.Action_Failed; + return retVal; + } + } + } + + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft) + { + FuncRetVal retVal = new FuncRetVal(); + WindowTop = 0; + WindowLeft = 0; + WindowWidth = 0; + WindowHeight = 0; + + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Found the document to close * Close it Without Prompting * + object saveOption = null; + if (bAutoSaveArtifact) + saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdSaveChanges; + else + saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges; + + object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat; + object routeDocument = false; + var app = doc.Application; + + // Let's get the Window that belongs to this document + Microsoft.Office.Interop.Word.Window docWindow = null; + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + docWindow = window; + } + + // Get the Window properties + WindowTop = docWindow.Top; + WindowLeft = docWindow.Left; + WindowWidth = docWindow.Width; + WindowHeight = docWindow.Height; + + //Object missing = Missing.Value; + doc.Close(ref saveOption, ref originalFormat, ref routeDocument); + Marshal.FinalReleaseComObject(doc); // force clean-up + + // Close the Window + if (docWindow != null) + docWindow.Close(ref saveOption, ref routeDocument); + + // Close Word if this is the Last Document Instance + if (app.Documents.Count == 0) + { + app.Quit(ref saveOption, ref originalFormat, ref routeDocument); + + Marshal.FinalReleaseComObject(docWindow); + Marshal.FinalReleaseComObject(app); // force clean-up, closes Process for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Found the document to close * Close it Without Prompting * + object saveOption = null; + if (bAutoSaveArtifact) + saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdSaveChanges; + else + saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges; + + object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat; + object routeDocument = false; + var app = doc.Application; + + // Let's get the Window that belongs to this document + Microsoft.Office.Interop.Word.Window docWindow = null; + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + docWindow = window; + } + + //Object missing = Missing.Value; + doc.Close(ref saveOption, ref originalFormat, ref routeDocument); + Marshal.FinalReleaseComObject(doc); // force clean-up + + // Close the Window + if (docWindow != null) + docWindow.Close(ref saveOption, ref routeDocument); + + // Close Word if this is the Last Document Instance + if (app.Documents.Count == 0) + { + app.Quit(ref saveOption, ref originalFormat, ref routeDocument); + + Marshal.FinalReleaseComObject(docWindow); + Marshal.FinalReleaseComObject(app); // force clean-up, closes Process for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + public FuncRetVal Close(string strArtifactLocation) + { + FuncRetVal retVal = new FuncRetVal(); + if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal)) + return retVal; + + try + { + var RunningWordDocuments = Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Found the document to close * Close it Without Prompting * + object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdSaveChanges; + object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat; + object routeDocument = false; + var app = doc.Application; + + // Let's get the Window that belongs to this document + Microsoft.Office.Interop.Word.Window docWindow = null; + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + docWindow = window; + } + + //Object missing = Missing.Value; + doc.Close(ref saveOption, ref originalFormat, ref routeDocument); + Marshal.FinalReleaseComObject(doc); // force clean-up + + // Close the Window + if (docWindow != null) + docWindow.Close(ref saveOption, ref routeDocument); + + // Close Word if this is the Last Document Instance + if (app.Documents.Count == 0) + { + app.Quit(ref saveOption, ref originalFormat, ref routeDocument); + + Marshal.FinalReleaseComObject(docWindow); + Marshal.FinalReleaseComObject(app); // force clean-up, closes Process for sure + } + + retVal.Type = FuncRetValEnum.Action_Succeeded; + return retVal; + } + } + retVal.Type = FuncRetValEnum.ArtifactUnavailable; + } + catch (Exception e) + { + retVal.Message = e.Message; + retVal.Type = FuncRetValEnum.ErrorThrown; + } + return retVal; + } + + } +} diff --git a/Client Services/ButtonWPForm/ButtonForm.xaml b/Client Services/ButtonWPForm/ButtonForm.xaml new file mode 100644 index 0000000..0ea6367 --- /dev/null +++ b/Client Services/ButtonWPForm/ButtonForm.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/Client Services/ButtonWPForm/ButtonForm.xaml.cs b/Client Services/ButtonWPForm/ButtonForm.xaml.cs new file mode 100644 index 0000000..024ec88 --- /dev/null +++ b/Client Services/ButtonWPForm/ButtonForm.xaml.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Runtime.InteropServices; +using System.Drawing; +using System.Reflection; +using SnapshotImage = System.Drawing.Image; + +// Ooganizer namespaces +using Foo.ClientServices.ButtonWPForm.ButtonFormPages; +using Foo.Platform; +using Foo.Platform.Win32; +using Foo.Platform.ErrorReporting; +using Foo.Platform.Interacters; +using System.Windows.Interop; + +namespace Foo.ClientServices.ButtonWPForm +{ + /// + /// Interaction logic for ButtonWindow Form + /// + [ComVisible(false)] + public partial class ButtonForm : Window + { + //// + // Public Properties + //// + public IntPtr HookedWindow { get { return _hHookedWnd; } set { _hHookedWnd = value; } } // Passed in by FormMgr + public System.Drawing.Image SnapShot { get { return _SnapShot; } set { _SnapShot = value; } } // Passed in by FormMgr + //public Artifact Artifact { get { return _Artifact; } } + //public string ArtifactTitle { get { return _ArtifactTitle; } } + //public string ArtifactLocation { get { return _ArtifactLocation; } } + //public string CurrentWorkspaceName { get { return _CurrentWorkspaceName; } } + + //// + // Private Member Variables + //// + private IntPtr _hHookedWnd = IntPtr.Zero; + private System.Drawing.Image _SnapShot = null; + private bool _PerformanceCache = false; + private static ButtonForm s_PerfCacheButtonFormObj = null; + private bool _PerfCacheLoadedHidden = false; + //private Artifact _Artifact; + //private string _ArtifactTitle; + //private string _ArtifactLocation; + //private string _CurrentWorkspaceName; + + //// + // ButtonFormPages + //// + IButtonFormPage[] m_ButtonFormPages = new IButtonFormPage[1]; + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Construct WPF ButtonForm :) + /// + public ButtonForm() + { + InitializeComponent(); + } + + /// + /// Construct WPF ButtonForm (Performance Cache) + /// + public ButtonForm(bool bPerformanceCache) + { + if (bPerformanceCache && (s_PerfCacheButtonFormObj == null)) + { + _PerformanceCache = bPerformanceCache; + s_PerfCacheButtonFormObj = this; + } + + InitializeComponent(); + } + + /// + /// As part of Performance Caching (load one instance of this form + /// hidden and not visible to the user (called by FormMgr) ~also + /// allows to hide and existing one + /// ~Should only be called by FormMgr when creating the first object + /// + public void LoadHideButtonFormPerfCache() + { + if (!_PerfCacheLoadedHidden && _PerformanceCache && (s_PerfCacheButtonFormObj != null)) + { + s_PerfCacheButtonFormObj.Opacity = 0; + s_PerfCacheButtonFormObj.WindowState = WindowState.Minimized; + s_PerfCacheButtonFormObj.ShowInTaskbar = false; + s_PerfCacheButtonFormObj.Show(); + s_PerfCacheButtonFormObj.Hide(); + _PerfCacheLoadedHidden = true; + } + } + + /// + /// Window Load Event. We want all object loading to happen in the Load Event, + /// because we construct the WPFForm and show it right away, so this is called right at + /// start up, so put all the object loading in here to be cleaner and simplify FormObject Creator + /// + private void OnLoad(object sender, RoutedEventArgs args) + { + try + { + if (_PerformanceCache && (this == s_PerfCacheButtonFormObj)) // Preload child pages + { + PreloadAllChildPages(); + + // Add Message Hook for performance WPForm * To make sure it is always invisible * + HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); + source.AddHook(new HwndSourceHook(MessageHook)); + } + else if (!_PerformanceCache && (HookedWindow != IntPtr.Zero) && (this != s_PerfCacheButtonFormObj)) + { + //// + // Resolve the Window and set the properties accordingly, + // our child pages depend on this information + //// + //ResolverDispatch resolver = new ResolverDispatch(); + //ArtifactGroup artifacts = resolver.GetArtifacts(HookedWindow); + + //if (artifacts.Length > 0) + //{ + // _Artifact = artifacts.GetPrimary; + // _ArtifactTitle = _Artifact.Name; + // _ArtifactLocation = _Artifact.Location; + + // // Workspace + // _CurrentWorkspaceName = SrvrCommon.GetCurrentWorkspaceName(); + + // // Now Load the Page + // LoadPageAccordingToState(); + //} + //else + //{ + // // Somemething went wrong Resolving + // UserError.Show("Document not Found", "Failed to accurately find the document for the Window"); + // Close(); //~imp, we must close this Form + //} + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - A fatal error occured loading ButtonForm", MethodBase.GetCurrentMethod().Name), e); + Close(); //~imp, we must close this Form + } + } + + /// + /// This Message Hook is for the Hidden WPForm that we use for better performance, + /// We want to make sure that it is never displayed *It can occur that explore can show it, without this* + /// + private IntPtr MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + // force opacity at all times + if (Opacity == 1.0) + Opacity = 0.0; + + // force minimized at all times + if (WindowState != WindowState.Minimized) + WindowState = WindowState.Minimized; + + // force Not to be seen in taskbar + if (ShowInTaskbar == true) + ShowInTaskbar = false; + + return System.IntPtr.Zero; + } + + /// + /// For Performance, we need to preload all Child Pages + /// + private void PreloadAllChildPages() + { + m_ButtonFormPages[0] = (IButtonFormPage) new Page_AddEdit(); + m_ButtonFormPages[0].ParentWPFContainer = this; + } + + /// + /// Show different pages depending on the state we are in. (Currently only 1 state) + /// + private void LoadPageAccordingToState() + { + m_ButtonFormPages[0] = (IButtonFormPage) new Page_AddEdit(); + m_ButtonFormPages[0].ParentWPFContainer = this; + + if (!frmButtonForm.Navigate((Page) m_ButtonFormPages[0])) + Log.Info(string.Format("{0}() - ButtonForm could not navigate to Page_AddEdit", MethodBase.GetCurrentMethod().Name)); + } + + /// + /// When this window closes position the Hooked Window back to it's original position + /// + private void Window_Closed(object sender, EventArgs e) + { + // GUICommon.PositionWindowBackToWhereItWas(HookedWindow, true); + BHInteracter.SetAsActiveWindow(HookedWindow); + } + } +} diff --git a/Client Services/ButtonWPForm/ButtonFormMgr.cs b/Client Services/ButtonWPForm/ButtonFormMgr.cs new file mode 100644 index 0000000..ee6ae40 --- /dev/null +++ b/Client Services/ButtonWPForm/ButtonFormMgr.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Drawing; +using System.Threading; +using System.Windows.Interop; +using System.EnterpriseServices; +using System.Windows; +using System.IO; +using System.Windows.Threading; +using System.Collections; +using System.Reflection; + +// Ooganizer Namespaces +using Foo.Platform; +using Foo.Platform.Win32; + +namespace Foo.ClientServices.ButtonWPForm +{ + /// + /// This class manages the creation/deletion and actions of (1 - n) ButtonForms + /// + [ComVisible(false)] + internal class ButtonFormMgr + { + private const int INITIAL_OBJECT_CAPACITY = 30; + private Hashtable m_ObjectList = null; + private Dispatcher m_Dispatcher = null; + + // we have one btnForm loaded (hidden) always, as a performance cache + private ButtonForm m_btnForm = null; + private bool m_IsBtnFormCached = false; + + // Imp! - allows external caller to run any action on a ButtonForm + public delegate void _Action(ButtonForm btnForm); + + //custom private delegates + private delegate void delegate_Create(int hParentWND, Image snapshot); + private delegate void delegate_Delete(int hParentWND); + private delegate int delegate_CreateWindow(int hParentWND); + private delegate void delegate_Action(int hParentWND, _Action action); + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + public ButtonFormMgr(Dispatcher disp) + { + m_ObjectList = new Hashtable(); + m_Dispatcher = disp; + + if (!m_IsBtnFormCached) + BetterPerformance(); + } + + /// + /// Calls Create_ButtonForm via Dispatcher if neccessary + /// + /// handle to Parent/Owner Window + public void Create_ButtonFormDISP(int hParentWND, Image snapshot) + { + if (hParentWND != 0) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + Create_ButtonForm(hParentWND, snapshot); + } + else + { + object[] parameters = new object[] { hParentWND, snapshot }; + m_Dispatcher.Invoke((delegate_Create)Create_ButtonFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + } + + /// + /// Calls Create_ButtonFormWindow via Dispatcher if neccessary + /// + /// handle to Parent/Owner Window + public int Create_ButtonFormWindowDISP(int hParentWND) + { + if (hParentWND != 0) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + return Create_ButtonFormWindow(hParentWND); + } + else + { + object[] parameters = new object[] { hParentWND }; + return (int)m_Dispatcher.Invoke((delegate_CreateWindow)Create_ButtonFormWindowDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + return 0; + } + + /// + /// Calls Delete_ButtonForm via Dispatcher if neccessary + /// + /// handle to Parent/Owner Window + public void Delete_ButtonFormDISP(int hParentWND) + { + if (hParentWND != 0) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + Delete_ButtonForm(hParentWND); + } + else + { + object[] parameters = new object[] { hParentWND }; + m_Dispatcher.Invoke((delegate_Delete)Delete_ButtonFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + } + + /// + /// Use this Dispatching Action Function to run any _Action on the ButtonForm + /// + /// handle to Parent/Owner Window + public void RunAction_ButtonFormDISP(int hParentWND, _Action action) + { + if (hParentWND != 0) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + RunAction_ButtonForm(hParentWND, action); + } + else + { + object[] parameters = new object[] { hParentWND, action }; + m_Dispatcher.Invoke((delegate_Action)RunAction_ButtonFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + } + + /// + /// Calls Terminate via Dispatcher if neccessary + /// + /// handle to Parent/Owner Window + public void TerminateDISP() + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + Terminate(); + } + else + { + m_Dispatcher.Invoke((Action)TerminateDISP, System.Windows.Threading.DispatcherPriority.Normal, null); + } + } + + /// + /// Creates a new ButtonForm object into the ObjectList + /// + /// handle to Parent/Owner Window + private void Create_ButtonForm(int hParentWND, Image snapshot) + { + try + { + if (!m_IsBtnFormCached) + BetterPerformance(); + + m_ObjectList[hParentWND] = new ButtonForm(); + ButtonForm btnForm = (ButtonForm)m_ObjectList[hParentWND]; + + if (btnForm != null) + { + // We use the InteropHelper to set the Owner Property + WindowInteropHelper InteropHelper = new WindowInteropHelper(btnForm); + InteropHelper.Owner = (IntPtr)hParentWND; + + // Set the important Fields into the Button Form + btnForm.HookedWindow = (IntPtr)hParentWND; // give it the handle to the hooked window + btnForm.SnapShot = snapshot; // give it the snapshot of the window + + RECT ParentWndRect = new RECT(); + Win32Functions.GetWindowRect((IntPtr)hParentWND, out ParentWndRect); + + // Get Initial Location for the form + btnForm.Top = ParentWndRect.top; + btnForm.Left = ParentWndRect.left; + + // Get Initial Height and Width of the form + btnForm.Height = (ParentWndRect.bottom - ParentWndRect.top); + btnForm.Width = (ParentWndRect.right - ParentWndRect.left); + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// Use this function to delete the ButtonForm Object + /// + /// handle to Parent/Owner Window + private void Delete_ButtonForm(int hParentWND) + { + try + { + if (m_ObjectList.ContainsKey(hParentWND)) + { + ButtonForm btnForm = (ButtonForm)m_ObjectList[hParentWND]; + if (btnForm != null) + { + m_ObjectList.Remove(hParentWND); + btnForm.Close(); + } + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// Use this to run void() function actions on the specified buttonform + /// + /// handle to Parent/Owner Window + /// a pointer to a delegate (action function) to run + private void RunAction_ButtonForm(int hParentWND, _Action action) + { + try + { + if (m_ObjectList.ContainsKey(hParentWND)) + { + ButtonForm btnForm = (ButtonForm)m_ObjectList[hParentWND]; + if (btnForm != null) + action(btnForm); + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// Use this to actually create the Window, call this after calling Create_ButtonForm + /// This will create the window by calling Show(), this will also show the window + /// + /// handle to Parent/Owner Window + /// the Handle to the newly created window object + private int Create_ButtonFormWindow(int hParentWND) + { + try + { + if (m_ObjectList.ContainsKey(hParentWND)) + { + ButtonForm btnForm = (ButtonForm)m_ObjectList[hParentWND]; + + // We use the InteropHelper to see if this WPFForm has been created previously + WindowInteropHelper InteropHelper = new WindowInteropHelper(btnForm); + if (InteropHelper.Handle == IntPtr.Zero) + { + btnForm.Show(); + } + return (int)InteropHelper.Handle; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + return 0; + } + + /// + /// Kills all ButtonForm Instances (STOPS ALL) + /// + private void Terminate() + { + try + { + foreach (object o in m_ObjectList) + { + if ((o != null) && (o is ButtonForm)) + { + ButtonForm btnForm = (ButtonForm)o; + btnForm.Close(); + } + } + m_ObjectList.Clear(); + + if (m_IsBtnFormCached) + { + m_btnForm.Close(); + m_IsBtnFormCached = false; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// In order to improve first WPForm performance we have one + /// WPForm ButtonForm loaded at all times. (opacity set to 0). + /// ~it has no parent setting so it is just a form of the desktop + /// + private void BetterPerformance() + { + if (!m_IsBtnFormCached) + { + try + { + // Performance Cache (keeps a window loaded always) + m_btnForm = new ButtonForm(true); + m_btnForm.LoadHideButtonFormPerfCache(); + m_IsBtnFormCached = true; + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + } + } +} diff --git a/Client Services/ButtonWPForm/ButtonFormPages/Page_AddEdit.xaml b/Client Services/ButtonWPForm/ButtonFormPages/Page_AddEdit.xaml new file mode 100644 index 0000000..0ca688a --- /dev/null +++ b/Client Services/ButtonWPForm/ButtonFormPages/Page_AddEdit.xaml @@ -0,0 +1,18 @@ + + + + + + diff --git a/Client Services/GUIDebugStepExe/GUIDebugStepTestForm.xaml.cs b/Client Services/GUIDebugStepExe/GUIDebugStepTestForm.xaml.cs new file mode 100644 index 0000000..42ee850 --- /dev/null +++ b/Client Services/GUIDebugStepExe/GUIDebugStepTestForm.xaml.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +// Foo Namespaces +using Foo.ClientServices.ButtonWPForm; +using Foo.ClientServices.GUIWPForms; + +namespace Foo.ClientServices.GUIDebugStepExe +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class GUIDebugStepTestForm : Window + { + + // Private Members + GUIWPForms.GUIWPForms m_Gui = null; + ButtonWPForm.ButtonWPFormCCW m_ButtonForm = null; + + public GUIDebugStepTestForm() + { + InitializeComponent(); + } + + private void btnLaunchArtifactWall_Click(object sender, RoutedEventArgs e) + { + m_Gui.LaunchArtifactWall(IntPtr.Zero); + } + + private void btnWorkspaceSelector_Click(object sender, RoutedEventArgs e) + { + m_Gui.LaunchWorkspaceSelector(IntPtr.Zero); + } + + private void btnSettingsNMain_Click(object sender, RoutedEventArgs e) + { + m_Gui.LaunchSettingsNAboutUs(IntPtr.Zero); + } + + private void btnButtonForm_Click(object sender, RoutedEventArgs e) + { + } + + private void wvGUIDebugStepTestForm_Loaded(object sender, RoutedEventArgs e) + { + // Instantiate the objects + m_Gui = new GUIWPForms.GUIWPForms(); + //m_ButtonForm = new ButtonWPForm.ButtonWPFormCCW(); + + // instantiate any dependent threads, etc + m_Gui.Start(); + //m_ButtonForm.Start(); + } + + private void wvGUIDebugStepTestForm_Closed(object sender, EventArgs e) + { + // close any dependent threads + m_Gui.Stop(); + //m_ButtonForm.Stop(); + + // delete objects + m_Gui = null; + //m_ButtonForm = null; + } + } +} diff --git a/Client Services/GUIDebugStepExe/Properties/AssemblyInfo.cs b/Client Services/GUIDebugStepExe/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d549f5b --- /dev/null +++ b/Client Services/GUIDebugStepExe/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GUIDebugStepExe")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GUIDebugStepExe")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Client Services/GUIDebugStepExe/Properties/Resources.Designer.cs b/Client Services/GUIDebugStepExe/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8728cf7 --- /dev/null +++ b/Client Services/GUIDebugStepExe/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.ClientServices.GUIDebugStepExe.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.ClientServices.GUIDebugStepExe.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Client Services/GUIDebugStepExe/Properties/Resources.resx b/Client Services/GUIDebugStepExe/Properties/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/Client Services/GUIDebugStepExe/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Client Services/GUIDebugStepExe/Properties/Settings.Designer.cs b/Client Services/GUIDebugStepExe/Properties/Settings.Designer.cs new file mode 100644 index 0000000..7f1368d --- /dev/null +++ b/Client Services/GUIDebugStepExe/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.ClientServices.GUIDebugStepExe.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Client Services/GUIDebugStepExe/Properties/Settings.settings b/Client Services/GUIDebugStepExe/Properties/Settings.settings new file mode 100644 index 0000000..8f2fd95 --- /dev/null +++ b/Client Services/GUIDebugStepExe/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Client Services/GUIWPForms/ComponentState.cs b/Client Services/GUIWPForms/ComponentState.cs new file mode 100644 index 0000000..9f7509a --- /dev/null +++ b/Client Services/GUIWPForms/ComponentState.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using System.Reflection; + +// Ooganizer Namespaces +using Foo.Platform; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// This class is responsible for launch all secondary threads required for this application as + /// well as hold any variables that are needed by all classes + /// created. + /// + [ComVisible(false)] + internal class ComponentState + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// This class manages the state / main variables of the COM+ that maybe needed by multiple classes. + /// It is responsible for starting and stopping any secondary threads. + /// + static ComponentState() + { + // We must subscribe to assembly resolver + Log.Info(string.Format("{0}() - GUIWPForms ComponentState() called. Application is starting...", MethodBase.GetCurrentMethod().Name)); + + // Let's Preload the Database *Right here, right now* that should be good for all of us + Data.Artifacts.DoesArtifactExistInSystem(DataTypeHelpers.CreateLocationOnlyArtifact("C:\\Dummy.file")); + + // Start GUI Dispatcher Thread + Log.Info(string.Format("{0}() - GUIWPForms ComponentState() called. Activating DispatcherThread", MethodBase.GetCurrentMethod().Name)); + DispatcherThread.Run = true; + } + + /// + /// Private Variables + /// + private static bool s_bApplicationIsRunning = false; + + /// + /// Use this to enable/disable all threads and variables for + /// the component states + /// + public static bool ApplicationIsRunning + { + get { return s_bApplicationIsRunning; } + set + { + if (!value) + { + Log.Info(string.Format("{0}() - ComponentState() sApplicationRunning set to False", MethodBase.GetCurrentMethod().Name)); + DispatcherThread.Run = false; + } + + s_bApplicationIsRunning = value; + } + } + + /// + /// Use this to access the GUIFormsMgr Object in order to + /// communicate to wpfForms (Setter should only be called by + /// DispatcherThread) + /// + public static GUIFormsMgr GUIFormsMgr + { + get { return DispatcherThread.s_GUIFormsMgr; } + } + } +} diff --git a/Client Services/GUIWPForms/DispatcherThread.cs b/Client Services/GUIWPForms/DispatcherThread.cs new file mode 100644 index 0000000..c53fada --- /dev/null +++ b/Client Services/GUIWPForms/DispatcherThread.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using System.Threading; +using System.Reflection; + +// Ooganizer Namespaces +using Foo.Platform; +using System.Windows.Threading; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// This class is responsible for creation and deltion of ButtonFormMgr.cs on a + /// Dispatcher Thread. ~The Dispatcher is responsible for all the messages being passed + /// for the Form Objects, it must be running at all times and created before any forms get + /// created. + /// + [ComVisible(false)] + class DispatcherThread + { + + // Member Variables + private static Thread s_DispatcherThread = null; + private static bool s_DispatcherThreadIsInitialized = false; + internal static GUIFormsMgr s_GUIFormsMgr = null; + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Constructor by default will launch the thread if needed + /// + static DispatcherThread() + { + Log.Info(string.Format("{0}() - DispatcherThread() called", MethodBase.GetCurrentMethod().Name)); + StartDispatcherThreadIfNeeded(); + } + + /// + /// Use this property to set the Dispatcher to running / not running + /// + public static bool Run + { + get { return s_DispatcherThreadIsInitialized; } + set + { + if (!value) + TerminateDispatcherThreadIfNeeded(); + + s_DispatcherThreadIsInitialized = value; + } + } + + /// + /// Message Loop Thread for wpfGUIForms + /// + private static void DispatcherThreadProc() + { + // Create ButtonFormMgr Object on this thread *Allow global access to the object* + Log.Info(string.Format("{0}() - About to new GUIFormsMgr via DispatcherThread", MethodBase.GetCurrentMethod().Name)); + s_GUIFormsMgr = new GUIFormsMgr(Dispatcher.CurrentDispatcher); + + Log.Info(string.Format("{0}() - GUIFormsMgr DispatcherThread is initialized s_DispatcherThreadIsInitialized is True", MethodBase.GetCurrentMethod().Name)); + s_DispatcherThreadIsInitialized = true; // always set to true to allow caller to exit out + + if (s_GUIFormsMgr != null) + { + Log.Info(string.Format("{0}() - GUIFormsMgr Launched via DispatcherThread", MethodBase.GetCurrentMethod().Name)); + + //Enter Dispatcher Message Loop + System.Windows.Threading.Dispatcher.Run(); + } + else + { + Log.Error(string.Format("{0}() - GUIFormsMgr Launch Failed! Exiting Thread - Major Error must have occured", MethodBase.GetCurrentMethod().Name)); + // exit thread - no need to stay here + } + } + + /// + /// Use this function to start ThreadProc(above) if needed. COM+ can shutdown the thread anytime, + /// we need to make sure that the thread is alive BEFORE calling ButtonForms + /// + private static void StartDispatcherThreadIfNeeded() + { + if (s_DispatcherThread != null && s_DispatcherThread.IsAlive) + { + return; + } + else + { + s_DispatcherThreadIsInitialized = false; + + // Start a new Thread so it can become the Message Loop + s_DispatcherThread = new Thread(new ThreadStart(DispatcherThread.DispatcherThreadProc)); + + // GUI components require the thread to be STA; otherwise throws an error + s_DispatcherThread.SetApartmentState(ApartmentState.STA); + Log.Info(string.Format("{0}() - Starting DispatcherThread...", MethodBase.GetCurrentMethod().Name)); + s_DispatcherThread.Start(); + Log.Info(string.Format("{0}() - DispatcherThread Started.", MethodBase.GetCurrentMethod().Name)); + + // Make sure the Application Object is running + // (COM will eventually just time out otherwise) + //while (!s_DispatcherThreadIsInitialized) + // System.Threading.Thread.Sleep(20); // Syncronous call + } + } + + /// + /// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown* + /// + private static void TerminateDispatcherThreadIfNeeded() + { + if (s_DispatcherThreadIsInitialized) + { + // Delete s_GUIFormsMgr and all wpfForms from this thread + s_GUIFormsMgr.TerminateDISP(); + s_GUIFormsMgr = null; + + s_DispatcherThread.Abort(); + s_DispatcherThreadIsInitialized = false; + Log.Info(string.Format("{0}() - GUIFormsMgr is DispatcherThread shutdown s_DispatcherThreadIsInitialized is False", MethodBase.GetCurrentMethod().Name)); + } + } + + } +} diff --git a/Client Services/GUIWPForms/GUIFormsMgr.cs b/Client Services/GUIWPForms/GUIFormsMgr.cs new file mode 100644 index 0000000..ed06472 --- /dev/null +++ b/Client Services/GUIWPForms/GUIFormsMgr.cs @@ -0,0 +1,381 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Drawing; +using System.Threading; +using System.Windows.Interop; +using System.EnterpriseServices; +using System.Windows; +using System.IO; +using System.Windows.Threading; +using System.Collections; +using System.Reflection; + +using Foo.Platform; +using Foo.GUILib; + +namespace Foo.ClientServices.GUIWPForms +{ + internal enum WPForms + { + ArtifactWall, + WorkspaceSelector, + SettingsNAboutUs, + } + + /// + /// Object Factory Creator for WPForms above + /// + internal class GUIWPFormsObjectFactory + { + /// + /// Object Form Factory for all our GUI Forms + /// + /// a WPF form object to create + /// true if to create a performanceCache window, should be false all other times + /// + public static Window CreateWPFormWindow(WPForms form, bool bPerformanceCache) + { + Window wpfForm = null; + switch (form) + { + case WPForms.ArtifactWall: + wpfForm = new ArtifactWall(bPerformanceCache); + break; + + case WPForms.WorkspaceSelector: + wpfForm = new WorkspaceSelector(bPerformanceCache); + break; + + case WPForms.SettingsNAboutUs: + wpfForm = new SettingsNAboutUs(bPerformanceCache); + break; + } + + // Imp! - if this is being loaded for performance we must handle it + WPFHiddenWindow.ExecuteShowOnAHiddenWindow(wpfForm, bPerformanceCache); + + return wpfForm; + } + } + + /// + /// This class manages the creation/deletion and actions of (1 - n) ButtonForms + /// + [ComVisible(false)] + internal class GUIFormsMgr + { + + private const int INITIAL_OBJECT_CAPACITY = 30; + private Hashtable m_ObjectList = null; + private Dispatcher m_Dispatcher = null; + + // load one instance of all wpforms (hidden) cached always, as a performance cache + private Window[] m_wpfCachedForms = null; + private bool m_AreWpfFormsCached = false; + + // Imp! - allows external caller to run any action on a Window + public delegate void _Action(Window wpfForm); + + //custom private delegates + private delegate bool delegate_Create(WPForms wpfFormType); + private delegate bool delegate_Show(WPForms wpfFormType); + private delegate bool delegate_Delete(WPForms wpfFormType); + private delegate bool delegate_Action(WPForms wpfFormType, _Action action); + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// GUIFormsMgr - Responsible for managing the GUI Window Messaging Threads + /// + /// Dispatcher Thread Context + public GUIFormsMgr(Dispatcher disp) + { + m_ObjectList = new Hashtable(); + m_Dispatcher = disp; + + if (!m_AreWpfFormsCached) + BetterPerformance(); + } + + /// + /// Calls Create_WpfForm via Dispatcher if neccessary + /// + /// Object type to create + public bool Create_WpfFormDISP(WPForms wpfFormType) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + return Create_WpfForm(wpfFormType); + } + else + { + object[] parameters = new object[] { wpfFormType }; + return (bool) m_Dispatcher.Invoke((delegate_Create)Create_WpfFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + + /// + /// Calls Show_WpfForm via Dispatcher if neccessary + /// + /// Object type to create + public bool Show_WpfFormDISP(WPForms wpfFormType) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + return Show_WpfForm(wpfFormType); + } + else + { + object[] parameters = new object[] { wpfFormType }; + return (bool) m_Dispatcher.Invoke((delegate_Create)Show_WpfFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + + /// + /// Calls Delete_WpfForm via Dispatcher if neccessary + /// + /// Object type to delete + public bool Delete_WpfFormDISP(WPForms wpfFormType) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + return Delete_WpfForm(wpfFormType); + } + else + { + object[] parameters = new object[] { wpfFormType }; + return (bool)m_Dispatcher.Invoke((delegate_Delete)Delete_WpfFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + + /// + /// Use this Dispatching Action Function to run any _Action on the WpfForm + /// + /// Object type to run action on + public bool RunAction_WpfFormDISP(WPForms wpfFormType, _Action action) + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + return RunAction_WpfForm(wpfFormType, action); + } + else + { + object[] parameters = new object[] { wpfFormType, action }; + return (bool) m_Dispatcher.Invoke((delegate_Action)RunAction_WpfFormDISP, System.Windows.Threading.DispatcherPriority.Normal, parameters); + } + } + + /// + /// Calls Terminate via Dispatcher if neccessary + /// + public void TerminateDISP() + { + if (m_Dispatcher.Thread == Thread.CurrentThread) + { + Terminate(); + } + else + { + m_Dispatcher.Invoke((Action)TerminateDISP, System.Windows.Threading.DispatcherPriority.Normal, null); + } + } + + /// + /// Creates a new WpfForm object into the ObjectList + /// + /// Object type to run action on + private bool Create_WpfForm(WPForms wpfFormType) + { + try + { + if (!m_AreWpfFormsCached) + BetterPerformance(); + + // we only allow one object * so delete the previous one if exists * + if (m_ObjectList[wpfFormType] != null) + Delete_WpfForm(wpfFormType); + + m_ObjectList[wpfFormType] = GUIWPFormsObjectFactory.CreateWPFormWindow(wpfFormType, false); + Window wpfForm = (Window) m_ObjectList[wpfFormType]; + + if (wpfForm == null) + { + Log.Error(string.Format("{0}() - Some Type of Error Occured. wpfForm is null", MethodBase.GetCurrentMethod().Name)); + return false; + } + else + { + return true; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Show a WpfForm object in the ObjectList + /// + /// Object type to run action on + private bool Show_WpfForm(WPForms wpfFormType) + { + try + { + Window wpfForm = (Window)m_ObjectList[wpfFormType]; + + if (wpfForm == null) + { + Log.Error(string.Format("{0}() - Some Type of Error Occured. wpfForm is null", MethodBase.GetCurrentMethod().Name)); + return false; + } + else + { + // We use the InteropHelper to see if this WPFForm has been created previously + WindowInteropHelper InteropHelper = new WindowInteropHelper(wpfForm); + if (InteropHelper.Handle == IntPtr.Zero) + { + wpfForm.Show(); + return true; + } + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Use this function to delete the WpfForm Object + /// + /// Object type to run action on + private bool Delete_WpfForm(WPForms wpfFormType) + { + try + { + if (m_ObjectList.ContainsKey(wpfFormType)) + { + Window wpfForm = (Window)m_ObjectList[wpfFormType]; + if (wpfForm != null) + { + m_ObjectList.Remove(wpfFormType); + wpfForm.Close(); + return true; + } + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Use this to run void() function actions on the specified wpfForm + /// + /// Object type to run action on + /// a pointer to a delegate (action function) to run + private bool RunAction_WpfForm(WPForms wpfFormType, _Action action) + { + try + { + if (m_ObjectList.ContainsKey(wpfFormType)) + { + Window wpfForm = (Window)m_ObjectList[wpfFormType]; + if (wpfForm != null && action != null) + { + action(wpfForm); + return true; + } + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Kills all ButtonForm Instances (STOPS ALL) + /// + private void Terminate() + { + try + { + foreach (object o in m_ObjectList) + { + if ((o != null) && (o is Window)) + { + Window WpfForm = (Window)o; + WpfForm.Close(); + } + } + m_ObjectList.Clear(); + + if (m_AreWpfFormsCached) + { + foreach (Window window in m_wpfCachedForms) + { + if (window != null) + window.Close(); + } + + // Caching is incomplete + m_AreWpfFormsCached = false; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// In order to improve WPForm performance we have one set of forms + /// loaded at all times. (opacity set to 0). + /// ~it has no parent setting so it is just a form of the desktop + /// + private void BetterPerformance() + { + if (!m_AreWpfFormsCached && (m_wpfCachedForms == null)) + { + try + { + lock (this) + { + int nForms = Enum.GetValues(typeof(WPForms)).Length; + if (nForms > 0) + { + // Allocate the cached forms array + m_wpfCachedForms = new Window[nForms]; + + // Iterate thru enums and create the corresponding objects in the Cache + for (int i = 0; i < nForms; ++i) + { + WPForms form = (WPForms)Enum.ToObject(typeof(WPForms), i); + m_wpfCachedForms[i] = GUIWPFormsObjectFactory.CreateWPFormWindow(form, true); + } + + // Caching is complete + m_AreWpfFormsCached = true; + } + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + } + } + } + + } +} diff --git a/Client Services/GUIWPForms/GUIState.cs b/Client Services/GUIWPForms/GUIState.cs new file mode 100644 index 0000000..77642e2 --- /dev/null +++ b/Client Services/GUIWPForms/GUIState.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +// Foo Namespaces +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using System.Windows; + +namespace Foo.ClientServices.GUIWPForms +{ + + /// + /// Used to save GUI State Information for all of GUIWPForms, + /// such as last selected SortOrder etc. ~very useful for having multiple forms + /// communicate with each other * C# Singleton # + /// + public static class GUIState + { + // WorkspaceSelector_StandardPage comboBox Workspace SortOrder + public static SortOrderForWorkspaces LastSelectedSotOrderWorkspaces { get; set; } + public static int LastSelectedSotOrderWorkspacesIndex { get; set; } + + // WorkspaceSelector_StandardPage dataGrid Selected WorkspaceName + public static string LastSelectedWorkspaceName { get; set; } + + // ArtifactWall + public static SortOrderForArtifacts LastSelectedSotOrderArtifacts { get; set; } + public static int LastSelectedSotOrderArtifactsIndex { get; set; } + + // Keeping track of launched WPF GUI's + public static Window CurrentlyShowingWPFWindow { get; set; } + + /// + /// Defaults + /// + static GUIState() + { + // Defaults for comboBox Workspace SortOrder + LastSelectedSotOrderWorkspaces = SortOrderForWorkspaces.Ascending; + LastSelectedSotOrderWorkspacesIndex = 0; + + // Defaults for Selected WorkspaceName + LastSelectedWorkspaceName = String.Empty; + + // Artifact Wall + LastSelectedSotOrderArtifacts = SortOrderForArtifacts.Ascending; + LastSelectedSotOrderArtifactsIndex = 0; + + // Keeping track of launched WPF GUI's + CurrentlyShowingWPFWindow = null; + } + } +} diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/AddWorkspace.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/AddWorkspace.png new file mode 100644 index 0000000..01bdc88 Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/AddWorkspace.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/Close.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Close.png new file mode 100644 index 0000000..21f27ff Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Close.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/CloseAll.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/CloseAll.png new file mode 100644 index 0000000..d758b0c Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/CloseAll.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/DeleteWorkspace.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/DeleteWorkspace.png new file mode 100644 index 0000000..2471d6a Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/DeleteWorkspace.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/EditWorkspace.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/EditWorkspace.png new file mode 100644 index 0000000..6a98752 Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/EditWorkspace.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/Hide.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Hide.png new file mode 100644 index 0000000..961c312 Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Hide.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/House.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/House.png new file mode 100644 index 0000000..17bb9ed Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/House.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/PageImages/Launch.png b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Launch.png new file mode 100644 index 0000000..288a59a Binary files /dev/null and b/Client Services/GUIWPForms/GUIWPFPages/PageImages/Launch.png differ diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml new file mode 100644 index 0000000..7581305 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml.cs b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml.cs new file mode 100644 index 0000000..2781d2e --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_DeleteWorkspacePage.xaml.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using System.Windows.Threading; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for WorkspaceSelector_DeleteWorkspacePage.xaml + /// + public partial class WorkspaceSelector_DeleteWorkspacePage : Page + { + // passed to us by parent + private WorkspaceSelector m_WorkspaceSelectorObj = null; + private bool m_bPerformanceCache = false; + + // private state variables + private string m_strWorkspaceName; + + public WorkspaceSelector_DeleteWorkspacePage(bool bPerformanceCache) + { + m_strWorkspaceName = String.Empty; + m_bPerformanceCache = bPerformanceCache; + if (!m_bPerformanceCache) + { + } + InitializeComponent(); + } + + /// + /// Occurs when page gets loaded + /// + private void Page_Loaded(object sender, RoutedEventArgs e) + { + if (!m_bPerformanceCache) + { + // Make sure that the Selector Frame is big enough to hold this page + m_WorkspaceSelectorObj = (WorkspaceSelector)this.Tag; + + // Make sure that we have a workspace Name to work with otherwise Navigate Back + if (String.IsNullOrEmpty(GUIState.LastSelectedWorkspaceName)) + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + else + m_strWorkspaceName = GUIState.LastSelectedWorkspaceName; + + // Set Height and Width + m_WorkspaceSelectorObj.Height = this.Height + m_WorkspaceSelectorObj.MarginTopBottom; + m_WorkspaceSelectorObj.Width = this.Width; + + // Set the Warning Label for this Particular Workspace + ConstructAreYouSureMessage(); + } + } + + /// + /// Constructs a thorough Warning Message to be displayed to the user in the label + /// Iterates and warns the user of exactly the number of changes that will occur in the system + /// + private void ConstructAreYouSureMessage() + { + int nArtifactsCount = Data.Artifacts.GetArtifactLinkCountForWorkspace(m_strWorkspaceName); + int nUniqueArtifactsCount = Data.Artifacts.GetUniqureArtifactsCountForWorkspace(m_strWorkspaceName); + if (nArtifactsCount >= 0 && nUniqueArtifactsCount >= 0) + { + StringBuilder sr = new StringBuilder(); + sr.Append(String.Format("Are you Sure you want to Delete Workspace '{0}'? \n\n", m_strWorkspaceName)); + sr.Append(String.Format("This Workspace contains {0} Artifact Links ", (nArtifactsCount - nUniqueArtifactsCount))); + sr.Append(String.Format("and {0} Artifacts. ", nUniqueArtifactsCount)); + sr.Append(String.Format("\n\n In Total: {0} Items will be deleted. There is no way to undo this operation.", nArtifactsCount)); + txtAreYouSure.Text = sr.ToString(); + } + else + { + // an error occured + Foo.Platform.ErrorReporting.UserError.Show("An Error Occurred", "Navigating you back to the WorkspaceSelector"); + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + } + + /// + /// Button Yes Event Handler - Go ahead and delete the workspace + /// + private void btnYes_Click(object sender, RoutedEventArgs e) + { + if (Data.Workspace.DeleteWorkspace(GUIState.LastSelectedWorkspaceName)) + { + + // Show Confirm Delete Message and Go Back + StringBuilder sr = new StringBuilder(); + sr.Append(String.Format("The Workspace '{0}' was deleted successfully. \n\n", m_strWorkspaceName)); + sr.Append("You will no longer be able to access this Workspace and any Artifacts that were exclusive to it."); + ShowMessageAndNavigateBack(sr.ToString()); + + // Set GUI State + GUIState.LastSelectedWorkspaceName = String.Empty; + } + else + { + // an error occured + Foo.Platform.ErrorReporting.UserError.Show("An Error Occurred", String.Format("An Error occured while deleting the Workspace {0}. Navigating you back to the WorkspaceSelector", m_strWorkspaceName)); + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + } + + /// + /// Shows the passed in message in the text box and then navigates back to the main page + /// + /// + private void ShowMessageAndNavigateBack(string strMessage) + { + // Hide the buttons + btnYes.Visibility = Visibility.Hidden; + btnNo.Visibility = Visibility.Hidden; + + // Show Message + txtAreYouSure.Text = strMessage; + + // Pause for 2 second and Navigate Back + DispatcherTimer dispatcherTimer = new DispatcherTimer(); + dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 500); + dispatcherTimer.Start(); + } + + /// + /// Timer set specifically to allow the message to be seen for a little bit before navigating back + /// + void dispatcherTimer_Tick(object sender, EventArgs e) + { + DispatcherTimer dispatcherTimer = (DispatcherTimer) sender; + dispatcherTimer.Stop(); + + // Navigate Back + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + + /// + /// Button No Event Handler - Go back to parent + /// + private void btnNo_Click(object sender, RoutedEventArgs e) + { + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + } +} diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml new file mode 100644 index 0000000..c118703 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml.cs b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml.cs new file mode 100644 index 0000000..d342aab --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_NewWorkspacePage.xaml.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Threading; +using System.Windows.Forms; +using System.Drawing; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for WorkspaceSelector_NewWorkspacePage.xaml + /// + public partial class WorkspaceSelector_NewWorkspacePage : Page + { + // passed to us by parent + private WorkspaceSelector m_WorkspaceSelectorObj = null; + private bool m_bPerformanceCache = false; + + // private state variables + private bool m_bIsValidName; + + public WorkspaceSelector_NewWorkspacePage(bool bPerformanceCache) + { + m_bPerformanceCache = bPerformanceCache; + if (!m_bPerformanceCache) + { + } + InitializeComponent(); + } + + private void Page_Loaded(object sender, RoutedEventArgs e) + { + if (!m_bPerformanceCache) + { + // Make sure that the Selector Frame is big enough to hold this page + m_WorkspaceSelectorObj = (WorkspaceSelector)this.Tag; + m_WorkspaceSelectorObj.Height = this.Height + m_WorkspaceSelectorObj.MarginTopBottom; + m_WorkspaceSelectorObj.Width = this.Width; + + // Set the Warning Label for this Particular Workspace + ConstructAreYouSureMessage(); + + // Set intial Error Message + SetWarningMessage("Enter Characters"); + m_bIsValidName = false; + + // Set intial focus + txtNewName.Focus(); + } + } + + /// + /// Constructs a renaming Message to be displayed to the user + /// + private void ConstructAreYouSureMessage() + { + StringBuilder sr = new StringBuilder(); + sr.Append("Create New Workspace \n"); + txtCreateWorkspaceTitle.Text = sr.ToString(); + } + + /// + /// Sets the validator label to a warning message + /// + /// + private void SetWarningMessage(string strMessage) + { + lblWarningMessage.Foreground = new SolidColorBrush(Colors.OrangeRed); + lblWarningMessage.Content = strMessage; + } + + /// + /// Sets the validator label to a success message + /// + /// + private void SetSuccessMessage(string strMessage) + { + lblWarningMessage.Foreground = new SolidColorBrush(Colors.RoyalBlue); + lblWarningMessage.Content = strMessage; + } + + /// + /// Button Yes Event Handler - Go ahead and Create the new WorkspaceName + /// + private void btnYes_Click(object sender, RoutedEventArgs e) + { + if (m_bIsValidName) + { + if (!DataAccessLayer.Data.Workspace.InsertWorkspaceName(txtNewName.Text)) + { + // an error occured + Foo.Platform.ErrorReporting.UserError.Show("An Error Occurred", "Creating the Workspace Failed! Navigating you back to the WorkspaceSelector"); + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + else + { + // Set GUI State + GUIState.LastSelectedWorkspaceName = txtNewName.Text; + + // Show Success Message + ShowMessageAndNavigateBack(String.Format("Workspace '{0}' has been successfully created", txtNewName.Text)); + } + } + } + + /// + /// Shows the passed in message in the text box and then navigates back to the main page + /// + /// + private void ShowMessageAndNavigateBack(string strMessage) + { + // Hide the buttons + btnYes.Visibility = Visibility.Hidden; + btnNo.Visibility = Visibility.Hidden; + + // Hide the textbox and Labels + lblEnterNewName.Visibility = Visibility.Hidden; + txtNewName.Visibility = Visibility.Hidden; + lblWarningMessage.Visibility = Visibility.Hidden; + + // Show Message + txtCreateWorkspaceTitle.Text = strMessage; + + // Dynamically calculate the height of the textbox * No need to do this in this case * + // System.Drawing.Size sz = new System.Drawing.Size((int)this.Width, int.MaxValue); + // Font font = new Font(txtRenameWorkspaceTitle.FontFamily.ToString(), (float)txtRenameWorkspaceTitle.FontSize); + // sz = TextRenderer.MeasureText(txtRenameWorkspaceTitle.Text, font, sz, TextFormatFlags.WordBreak); + // Change Height as needed + // lblRenameWorkspaceTitle.Height = sz.Height; + // txtRenameWorkspaceTitle.Height = sz.Height; + + // default to change height to Max available space + lblCreateWorkspaceTitle.Height = this.Height - m_WorkspaceSelectorObj.MarginTopBottom; + txtCreateWorkspaceTitle.Height = this.Height - m_WorkspaceSelectorObj.MarginTopBottom; + + // Pause for 1.5 second and Navigate Back + DispatcherTimer dispatcherTimer = new DispatcherTimer(); + dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 500); + dispatcherTimer.Start(); + } + + /// + /// Timer set specifically to allow the message to be seen for a little bit before navigating back + /// + void dispatcherTimer_Tick(object sender, EventArgs e) + { + DispatcherTimer dispatcherTimer = (DispatcherTimer)sender; + dispatcherTimer.Stop(); + + // Navigate Back + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + + /// + /// Button No Event Handler - Go back to parent + /// + private void btnNo_Click(object sender, RoutedEventArgs e) + { + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + + /// + /// Perform NewWorkspaceName TextBox Validation + /// + private void txtNewName_TextChanged(object sender, TextChangedEventArgs e) + { + System.Windows.Controls.TextBox textBox = (System.Windows.Controls.TextBox)sender; + if (String.IsNullOrEmpty(textBox.Text)) + { + SetWarningMessage("Enter Characters"); + m_bIsValidName = false; + } + else if (!DataAccessLayer.DataTypes.DataTypeValidation.IsValidWorkspaceName(textBox.Text)) + { + SetWarningMessage("Invalid Workspace Name"); + m_bIsValidName = false; + } + else if (DataAccessLayer.Data.Workspace.DoesWorkspaceNameExist(textBox.Text)) + { + SetWarningMessage("Workspace Name Already Exists"); + m_bIsValidName = false; + } + else + { + SetSuccessMessage("Valid Workspace Name"); + m_bIsValidName = true; + } + } + } +} diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml new file mode 100644 index 0000000..d56356f --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml.cs b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml.cs new file mode 100644 index 0000000..d951b1b --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_RenameWorkspacePage.xaml.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Threading; +using System.Windows.Forms; +using System.Drawing; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for WorkspaceSelector_RenameWorkspacePage.xaml + /// + public partial class WorkspaceSelector_RenameWorkspacePage : Page + { + // passed to us by parent + private WorkspaceSelector m_WorkspaceSelectorObj = null; + private bool m_bPerformanceCache = false; + + // private state variables + private string m_strWorkspaceName; + private bool m_bIsValidName; + + public WorkspaceSelector_RenameWorkspacePage(bool bPerformanceCache) + { + m_bPerformanceCache = bPerformanceCache; + if (!m_bPerformanceCache) + { + } + InitializeComponent(); + } + + private void Page_Loaded(object sender, RoutedEventArgs e) + { + if (!m_bPerformanceCache) + { + // Make sure that the Selector Frame is big enough to hold this page + m_WorkspaceSelectorObj = (WorkspaceSelector)this.Tag; + + // Make sure that we have a workspace Name to work with otherwise Navigate Back + if (String.IsNullOrEmpty(GUIState.LastSelectedWorkspaceName)) + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + else + m_strWorkspaceName = GUIState.LastSelectedWorkspaceName; + + // Set Height and Width + m_WorkspaceSelectorObj.Height = this.Height + m_WorkspaceSelectorObj.MarginTopBottom; + m_WorkspaceSelectorObj.Width = this.Width; + + // Set the Warning Label for this Particular Workspace + ConstructAreYouSureMessage(); + + // Set intial Error Message + SetWarningMessage("Enter Characters"); + m_bIsValidName = false; + + // Set intial focus + txtNewName.Focus(); + } + } + + /// + /// Constructs a renaming Message to be displayed to the user + /// + private void ConstructAreYouSureMessage() + { + StringBuilder sr = new StringBuilder(); + sr.Append(String.Format("Rename Workspace '{0}'\n", m_strWorkspaceName)); + txtRenameWorkspaceTitle.Text = sr.ToString(); + } + + /// + /// Sets the validator label to a warning message + /// + /// + private void SetWarningMessage(string strMessage) + { + lblWarningMessage.Foreground = new SolidColorBrush(Colors.OrangeRed); + lblWarningMessage.Content = strMessage; + } + + /// + /// Sets the validator label to a success message + /// + /// + private void SetSuccessMessage(string strMessage) + { + lblWarningMessage.Foreground = new SolidColorBrush(Colors.RoyalBlue); + lblWarningMessage.Content = strMessage; + } + + /// + /// Button Yes Event Handler - Go ahead and Rename the WorkspaceName + /// + private void btnYes_Click(object sender, RoutedEventArgs e) + { + if (m_bIsValidName) + { + if (!DataAccessLayer.Data.Workspace.RenameWorkspace(m_strWorkspaceName, txtNewName.Text)) + { + // an error occured + Foo.Platform.ErrorReporting.UserError.Show("An Error Occurred", "Renaming the Workspace Failed! Navigating you back to the WorkspaceSelector"); + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + else + { + // Set GUI State + GUIState.LastSelectedWorkspaceName = txtNewName.Text; + + // Show Success Message + ShowMessageAndNavigateBack(String.Format("'{0}' has been successfully renamed to '{1}'", m_strWorkspaceName, txtNewName.Text)); + } + } + } + + /// + /// Shows the passed in message in the text box and then navigates back to the main page + /// + /// + private void ShowMessageAndNavigateBack(string strMessage) + { + // Hide the buttons + btnYes.Visibility = Visibility.Hidden; + btnNo.Visibility = Visibility.Hidden; + + // Hide the textbox and Labels + lblEnterNewName.Visibility = Visibility.Hidden; + txtNewName.Visibility = Visibility.Hidden; + lblWarningMessage.Visibility = Visibility.Hidden; + + // Show Message + txtRenameWorkspaceTitle.Text = strMessage; + + // Dynamically calculate the height of the textbox * No need to do this in this case * + // System.Drawing.Size sz = new System.Drawing.Size((int)this.Width, int.MaxValue); + // Font font = new Font(txtRenameWorkspaceTitle.FontFamily.ToString(),(float) txtRenameWorkspaceTitle.FontSize); + // sz = TextRenderer.MeasureText(txtRenameWorkspaceTitle.Text, font, sz, TextFormatFlags.WordBreak); + // Change Height as needed + // lblRenameWorkspaceTitle.Height = sz.Height; + // txtRenameWorkspaceTitle.Height = sz.Height; + + // default to change height to Max available space + lblRenameWorkspaceTitle.Height = this.Height - m_WorkspaceSelectorObj.MarginTopBottom; + txtRenameWorkspaceTitle.Height = this.Height - m_WorkspaceSelectorObj.MarginTopBottom; + + // Pause for 1.5 second and Navigate Back + DispatcherTimer dispatcherTimer = new DispatcherTimer(); + dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 500); + dispatcherTimer.Start(); + } + + /// + /// Timer set specifically to allow the message to be seen for a little bit before navigating back + /// + void dispatcherTimer_Tick(object sender, EventArgs e) + { + DispatcherTimer dispatcherTimer = (DispatcherTimer)sender; + dispatcherTimer.Stop(); + + // Navigate Back + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + + /// + /// Button No Event Handler - Go back to parent + /// + private void btnNo_Click(object sender, RoutedEventArgs e) + { + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + } + + /// + /// Perform NewWorkspaceName TextBox Validation + /// + private void txtNewName_TextChanged(object sender, TextChangedEventArgs e) + { + System.Windows.Controls.TextBox textBox = (System.Windows.Controls.TextBox)sender; + if (String.IsNullOrEmpty(textBox.Text)) + { + SetWarningMessage("Enter Characters"); + m_bIsValidName = false; + } + else if (!DataAccessLayer.DataTypes.DataTypeValidation.IsValidWorkspaceName(textBox.Text)) + { + SetWarningMessage("Invalid Workspace Name"); + m_bIsValidName = false; + } + else if (DataAccessLayer.Data.Workspace.DoesWorkspaceNameExist(textBox.Text)) + { + SetWarningMessage("Workspace Name Already Exists"); + m_bIsValidName = false; + } + else + { + SetSuccessMessage("Valid Workspace Name"); + m_bIsValidName = true; + } + } + } +} diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml new file mode 100644 index 0000000..c5b5c68 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml.cs b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml.cs new file mode 100644 index 0000000..ece8dc3 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPFPages/WorkspaceSelector_StandardPage.xaml.cs @@ -0,0 +1,418 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Collections.ObjectModel; +using Microsoft.Windows.Controls; +using System.Data; +using System.ComponentModel; + +// Foo Namespace +using Foo.WorkspaceMgr; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using Foo.GUILib; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for WorkspaceSelector_StandardPage.xaml + /// + public partial class WorkspaceSelector_StandardPage : Page + { + // passed to us by parent + private WorkspaceSelector m_WorkspaceSelectorObj = null; + private bool m_bPerformanceCache = false; + + // WorkspaceMgr - Imp + private WorkspaceMgr.WorkspaceMgr m_WorkspaceMgr = null; + + // private DT holds all information needed for the DataGrid + public DataTable WorkspacesDT { get; private set; } + + /// + /// Constructor + /// + /// + public WorkspaceSelector_StandardPage(bool bPerformanceCache) + { + // We preload & require the WorkspaceMgr in this class + m_WorkspaceMgr = new WorkspaceMgr.WorkspaceMgr(); + + // Preload Database call - to make sure it is fast when the user sees it + String[] workspaceNames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + + m_bPerformanceCache = bPerformanceCache; + if (!m_bPerformanceCache) + { + } + + InitializeComponent(); + } + + /// + /// Called when we want to Update the DataGrid with new DataTable Items + /// ~Responsible for reloading the WorkspacesDT + /// + private void UpdateWorkspaceGridItems(SortOrderForWorkspaces sortOrder) + { + // First Step - Clear the Grid + WorkspacesDT.Rows.Clear(); + + // Second Step - Fill the Grid with the WorkspaceNames + String[] workspaceNames = Data.Workspace.GetAllWorkspaceNames(sortOrder); + + int i = 0; + int selectedIndex = -1; + foreach (string workspaceName in workspaceNames) + { + var row = WorkspacesDT.NewRow(); + WorkspacesDT.Rows.Add(row); + row["WorkspaceName"] = workspaceName; + row["ButtonResUri"] = "PageImages/Launch.png";//"PageImages/Launch.png"; + row["ButtonToolTipText"] = "Launch This Workspace"; + + // Let's Determine which index is supposed to be selected + if (!String.IsNullOrEmpty(GUIState.LastSelectedWorkspaceName) && + (workspaceName == GUIState.LastSelectedWorkspaceName)) + selectedIndex = i; + + i = i + 1; // incr. + } + + // Third Step - Refresh The DataGrid + dataGridWorkspaces.ItemsSource = WorkspacesDT.DefaultView; + // Other ways to refresh * appears to not be needed here * could be useful later + //dataGridWorkspaces.ItemsSource = (WorkspacesDT as IListSource).GetList(); + //dataGridWorkspaces.Items.Refresh(); + + // Fourth Step - Reset the ColumnWidth of the WorkspaceName if no Scrollbar is visible + if (workspaceNames.Length <= 13) + { + // scrollbar not visible + DataGridLength gridbuffer = new DataGridLength(188 + 18); + dataGridWorkspaces.Columns[0].Width = gridbuffer; + } + else + { + // scrollbar visible + DataGridLength gridbuffer = new DataGridLength(188); + dataGridWorkspaces.Columns[0].Width = gridbuffer; + } + + // Fifth Step - Set the Selected Index of the DataGrid to the last set + // Workspace Or 0 if not found + if (selectedIndex >= 0) + dataGridWorkspaces.SelectedIndex = selectedIndex; + else + dataGridWorkspaces.SelectedIndex = 0; + } + + #region Page Events + + /// + /// Called when the Page is loaded + /// + private void Page_Loaded(object sender, RoutedEventArgs e) + { + if (!m_bPerformanceCache) + { + // Make sure that the Selector Frame is big enough to hold this page + m_WorkspaceSelectorObj = (WorkspaceSelector)this.Tag; + m_WorkspaceSelectorObj.Height = this.Height + m_WorkspaceSelectorObj.MarginTopBottom; + m_WorkspaceSelectorObj.Width = this.Width; + + // InitializeWorkspaceDT + WorkspacesDT = new DataTable("WorkspaceData"); + WorkspacesDT.Columns.Add(new DataColumn("WorkspaceName", typeof(string))); + WorkspacesDT.Columns.Add(new DataColumn("ButtonResUri", typeof(string))); + WorkspacesDT.Columns.Add(new DataColumn("ButtonToolTipText", typeof(string))); + + // Set Workspaces Label + lblCurrentWorkspace.Content = "Workspaces"; + + // Load ComboBox Sort Orders + comboBoxSortBy.Items.Add(WPFHelper.CreateAComboBoxItem("Sort By Last Accessed", SortOrderForWorkspaces.LastAccessedDescending)); + comboBoxSortBy.Items.Add(WPFHelper.CreateAComboBoxItem("Sort By Most Frequently Used", SortOrderForWorkspaces.MostFrequentlyAccessedDescending)); + comboBoxSortBy.Items.Add(WPFHelper.CreateAComboBoxItem("Sort By Name", SortOrderForWorkspaces.Ascending)); + + // Load GUI State (or Default Index) + comboBoxSortBy.SelectedIndex = GUIState.LastSelectedSotOrderWorkspacesIndex; + + // Assign ToolTips for the Buttons + btnNew.ToolTip = WPFHelper.CreateNewStringToolTip("New Workspace", 0, 120); + btnEdit.ToolTip = WPFHelper.CreateNewStringToolTip("Rename Workspace", 0, 120); + btnDelete.ToolTip = WPFHelper.CreateNewStringToolTip("Delete Workspace", 0, 120); + btnCloseAll.ToolTip = WPFHelper.CreateNewStringToolTip("Close All Workspaces", 0, 120); + } + } + + #endregion + + #region ComboBox Events + + /// + /// Combo Box - SortBy - Selection Change Event * Deal with repopulating the Workspace Datagrid + /// + private void comboBoxSortBy_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + ComboBox combobox = sender as ComboBox; + if (combobox != null) + { + ComboBoxItem item = (ComboBoxItem)combobox.SelectedItem; + string Content = item.Content.ToString(); + SortOrderForWorkspaces sortOrder = (SortOrderForWorkspaces)item.Tag; + + // Save the State Information * Last SortOrder and Last SortOrder Index * + GUIState.LastSelectedSotOrderWorkspaces = sortOrder; + GUIState.LastSelectedSotOrderWorkspacesIndex = combobox.SelectedIndex; + + // Update The Grid + UpdateWorkspaceGridItems(sortOrder); + } + } + + #endregion + + #region DataGrid Events + + /// + /// Upon double-click we should be launching the Workspace (unload any previously loaded ones) + /// + private void dataGridWorkspaces_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + { + + } + } + + /// + /// Selection changed - Keep track of last selected workspace in GUIState + /// + private void dataGridWorkspaces_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e) + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + GUIState.LastSelectedWorkspaceName = strWorkspaceName; + } + + /// + /// Get Whatever Workspace the User currently has selected in the Grid + /// + /// Selected Workpsace Or Empty String if there is none + private string dataGrid_GetSelectedWorkspaceIfThereIsOne() + { + String strWorkspaceName = String.Empty; + + // We only allow single selection + IList cells = dataGridWorkspaces.SelectedCells; + if (cells.Count > 0) + { + DataGridCellInfo cell = cells[0]; + DataRowView row = (DataRowView)cell.Item; + strWorkspaceName = row["WorkspaceName"].ToString(); + } + return strWorkspaceName; + } + + /// + /// Creates the DataGrid Context Menu according to the Selected Workspace State + /// + /// valid Context Menu or Null + private ContextMenu dataGrid_CreateDataGridContextMenu() + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + { + // We also want to load the state of the workspace here + ContextMenu menu = new ContextMenu(); + menu.PlacementTarget = this; + + // Load all the MenuItems + MenuItem m1 = new MenuItem(); + m1.Header = "Launch"; + m1.Click += new RoutedEventHandler(ContextMenu_Item_Click); + m1.FontWeight = FontWeights.Bold; + m1.Icon = WPFHelper.CreateWPFImageFromRelativeResourceUri("PageImages/Launch.png", 16, 16); + menu.Items.Add(m1); + + MenuItem m2 = new MenuItem(); + m2.Header = "Show"; + m2.Click += new RoutedEventHandler(ContextMenu_Item_Click); + m2.Icon = WPFHelper.CreateWPFImageFromRelativeResourceUri("PageImages/Hide.png", 16, 16); + menu.Items.Add(m2); + + MenuItem m3 = new MenuItem(); + m3.Header = "Hide"; + m3.Click += new RoutedEventHandler(ContextMenu_Item_Click); + m3.Icon = WPFHelper.CreateWPFImageFromRelativeResourceUri("PageImages/Hide.png", 16, 16); + menu.Items.Add(m3); + + MenuItem m4 = new MenuItem(); + m4.Header = "Close"; + m4.Click += new RoutedEventHandler(ContextMenu_Item_Click); + m4.Icon = WPFHelper.CreateWPFImageFromRelativeResourceUri("PageImages/Close.png", 16, 16); + menu.Items.Add(m4); + + // Load all the Events + menu.Closed += new RoutedEventHandler(ContextMenu_Closed); + menu.MouseLeave += new MouseEventHandler(ContextMenu_MouseLeave); + return menu; + } + return null; + } + + /// + /// We need to manually implement the context menu upon right click and not use wpf, + /// because of the mouse leave event + /// + private void dataGridWorkspaces_MouseRightButtonDown(object sender, MouseButtonEventArgs e) + { + ContextMenu menu = dataGrid_CreateDataGridContextMenu(); + if (menu != null) + { + // Make sure that leave doesn't work + m_WorkspaceSelectorObj.DontCloseOnMouseLeave = true; + + // Show the Context Menu + menu.IsOpen = true; + } + } + + #endregion + + #region ContextMenu Events + + /// + /// Context Menu - Closed Event + /// + void ContextMenu_Closed(object sender, RoutedEventArgs e) + { + // Make sure that navigator leave works again + m_WorkspaceSelectorObj.DontCloseOnMouseLeave = false; + + // Close the Navigation Form *if the mouse is NOT over it* + if (!WPFHelper.IsMouseCursorOverWPFormWindow(m_WorkspaceSelectorObj)) + m_WorkspaceSelectorObj.Close(); + } + + /// + /// Context Menu - Mouse Leave Event + /// + void ContextMenu_MouseLeave(object sender, MouseEventArgs e) + { + // On Leave just close the Menu + ContextMenu menu = (ContextMenu)sender; + menu.IsOpen = false; + } + + /// + /// Context Menu - Menu Item Clicked Event + /// + void ContextMenu_Item_Click(object sender, RoutedEventArgs e) + { + MenuItem m = (MenuItem)sender; + + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + { + bool bSuccess = false; + switch (m.Header.ToString()) + { + case "Launch": + { + bSuccess = m_WorkspaceMgr.LaunchWorkspace(strWorkspaceName); + } + break; + + case "Show": + { + bSuccess = m_WorkspaceMgr.HideShowWorkspace(strWorkspaceName, true); + } + break; + + case "Hide": + { + bSuccess = m_WorkspaceMgr.HideShowWorkspace(strWorkspaceName, false); + } + break; + + case "Close": + { + bSuccess = m_WorkspaceMgr.CloseWorkspace(strWorkspaceName); + } + break; + } + } + } + + #endregion + + #region Button Click Events + + /// + /// New Button - Event Handler + /// + private void btnNew_Click(object sender, RoutedEventArgs e) + { + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_NewWorkspacePage); + } + + /// + /// Edit Button - Event Handler + /// + private void btnEdit_Click(object sender, RoutedEventArgs e) + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + { + GUIState.LastSelectedWorkspaceName = strWorkspaceName; + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_RenameWorkspacePage); + } + } + + /// + /// Delete Button - Event Handler + /// + private void btnDelete_Click(object sender, RoutedEventArgs e) + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (!String.IsNullOrEmpty(strWorkspaceName)) + { + GUIState.LastSelectedWorkspaceName = strWorkspaceName; + m_WorkspaceSelectorObj.NavigateToChildPage(ChildPages.WorkspaceSelector_DeleteWorkspacePage); + } + } + + /// + /// CloseAll Button - Event Handler + /// + private void btnCloseAll_Click(object sender, RoutedEventArgs e) + { + MessageBox.Show("Does Nothing"); + } + + /// + /// Button on the Grid is being clicked - Event Handler + /// + private void ButtonGrid_Click(object sender, RoutedEventArgs e) + { + string strWorkspaceName = dataGrid_GetSelectedWorkspaceIfThereIsOne(); + if (String.IsNullOrEmpty(strWorkspaceName)) + return; + } + + #endregion + } +} diff --git a/Client Services/GUIWPForms/GUIWPForms.cs b/Client Services/GUIWPForms/GUIWPForms.cs new file mode 100644 index 0000000..f72febb --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms.cs @@ -0,0 +1,237 @@ +// For GUIDebugStepExe Debugging Only - Uncomment this #define +#define GUIDEBUGSTEPEXE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Runtime.InteropServices; +using System.Windows.Interop; +using System.EnterpriseServices; +using System.Reflection; + +using Foo.Platform; +using Foo.Platform.Win32; +using System.Windows; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// GUIWPForms - Com Callable Wrapper Class exposed to ButtonHook. + /// This class is responsible for creating the ButtonWPForm (a form created in response to a ButtonHook W32 Click) + /// + [Guid("481C24F8-D619-460b-955A-22055571430C")] + [ClassInterface(ClassInterfaceType.None)] + [ProgId("Foo.ClientServices.GUIWPForms")] + [ComVisible(true)] + [ObjectPooling(Enabled = true, MinPoolSize = 1, MaxPoolSize = 2500, CreationTimeout = 5000)] +#if GUIDEBUGSTEPEXE + public class GUIWPForms : IGUIPWPForms +#else + public class GUIWPForms : ServicedComponent, IProcessInitializer, IGUIPWPForms +#endif + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + #region Construction / Destruction + public GUIWPForms() {} + ~GUIWPForms() { } + #endregion + +#if GUIDEBUGSTEPEXE + #region GuiDebugStepCustomStarterStopers + public void Start() + { + Log.Info(string.Format("{0}() - ComponentState Application Is being started", MethodBase.GetCurrentMethod().Name)); + ComponentState.ApplicationIsRunning = true; + } + + public void Stop() + { + Log.Info(string.Format("{0}() - ComponentState Application Is being stopped", MethodBase.GetCurrentMethod().Name)); + ComponentState.ApplicationIsRunning = false; + } + #endregion +#else + #region IProcessInitializer Members + public void Startup(object punkProcessControl) + { + Log.Info(string.Format("{0}() - ComponentState Application Is being started", MethodBase.GetCurrentMethod().Name)); + ComponentState.ApplicationIsRunning = true; + } + + public void Shutdown() + { + Log.Info(string.Format("{0}() - ComponentState Application Is being stopped", MethodBase.GetCurrentMethod().Name)); + ComponentState.ApplicationIsRunning = false; + } + #endregion +#endif + + #region IGUIPWPForms Members + + /// + /// Launches the ArtifactWall WPForm (if one already exists, relaunches) + /// + /// handle to the Button on the Deskband (used for positioning) + /// true if successful, false otherwise + public bool LaunchArtifactWall(IntPtr hDeskbandButtonWnd) + { + try + { + RECT rect; + bool bFillRect = false; + if (hDeskbandButtonWnd != IntPtr.Zero) + bFillRect = Win32Functions.GetWindowRect(hDeskbandButtonWnd, out rect); + + // First Step - Create the WpfForm + ComponentState.GUIFormsMgr.Create_WpfFormDISP(WPForms.ArtifactWall); + + // Second Step - If we have a Rect, set the location + if (bFillRect) + { + //GUIFormsMgr._Action action = new GUIFormsMgr._Action(delegate(Window wpfForm) + //{ + // wpfForm.Height = nHeight; + // wpfForm.Width = nWidth; + //}); + //ComponentState.GUIFormsMgr.RunAction_WpfFormDISP(WPForms.ArtifactWall, action); + } + + // Third Step - Show the WpfForm + ComponentState.GUIFormsMgr.Show_WpfFormDISP(WPForms.ArtifactWall); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + } + return true; + } + + /// + /// Closes the ArtifactWall if exists + /// + /// true if closed, false if not existent + public bool CloseArtifactWall() + { + try + { + return ComponentState.GUIFormsMgr.Delete_WpfFormDISP(WPForms.ArtifactWall); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Launches the WorkspaceSelector WPForm (if one already exists, relaunches) + /// + /// handle to the Button on the Deskband (used for positioning) + /// true if successful, false otherwise + public bool LaunchWorkspaceSelector(IntPtr hDeskbandButtonWnd) + { + try + { + RECT rect = new RECT(); + rect.top = 0; + rect.left = 0; + bool bSuccess = false; + bool bFillRect = false; + if (hDeskbandButtonWnd != IntPtr.Zero) + bFillRect = Win32Functions.GetWindowRect(hDeskbandButtonWnd, out rect); + + // First Step - Create the WpfForm + bSuccess = ComponentState.GUIFormsMgr.Create_WpfFormDISP(WPForms.WorkspaceSelector); + if (!bSuccess) + return false; + + // Second Step - If we have a Rect, set the location of the Workspace Selector + if (bFillRect) + { + GUIFormsMgr._Action action = new GUIFormsMgr._Action(delegate(Window wpfForm) + { + wpfForm.Top = rect.top + rect.AsRectangle.Height + 2; + wpfForm.Left = rect.left - 200; + }); + bSuccess = ComponentState.GUIFormsMgr.RunAction_WpfFormDISP(WPForms.WorkspaceSelector, action); + if (!bSuccess) + return false; + } + + // Third Step - Show the WpfForm + bSuccess = ComponentState.GUIFormsMgr.Show_WpfFormDISP(WPForms.WorkspaceSelector); + if (!bSuccess) + return false; + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + return false; + } + return true; + } + + /// + /// Closes the WorkspaceSelector if exists + /// + /// + /// true if closed, false if not existent + public bool CloseWorkspaceSelector() + { + try + { + return ComponentState.GUIFormsMgr.Delete_WpfFormDISP(WPForms.WorkspaceSelector); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + /// + /// Launches the Settings and Abouts WPForm (if one already exists, relaunches) + /// + /// handle to the Button on the Deskband (used for positioning) + /// true if successful, false otherwise + public bool LaunchSettingsNAboutUs(IntPtr hDeskbandButtonWnd) + { + try + { + // First Step - Create the WpfForm + ComponentState.GUIFormsMgr.Create_WpfFormDISP(WPForms.SettingsNAboutUs); + + // Second Step - Show the WpfForm + ComponentState.GUIFormsMgr.Show_WpfFormDISP(WPForms.SettingsNAboutUs); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + } + return true; + } + + /// + /// Closes the Settings And About us + /// + /// true if closed, false if not existent + public bool CloseSettingsNAboutUs() + { + try + { + return ComponentState.GUIFormsMgr.Delete_WpfFormDISP(WPForms.WorkspaceSelector); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Occured", MethodBase.GetCurrentMethod().Name), e); + } + return false; + } + + #endregion + } +} diff --git a/Client Services/GUIWPForms/GUIWPForms.csproj b/Client Services/GUIWPForms/GUIWPForms.csproj new file mode 100644 index 0000000..da59d58 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms.csproj @@ -0,0 +1,212 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {A02E052C-3C52-43DB-BB30-A47446B8165F} + Library + Properties + Foo.ClientServices.GUIWPForms + GUIWPForms + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + + + + + + + + + true + MyKeyFile.SNK + + + true + full + false + ..\..\Target\Debug\ + TRACE;DEBUG + prompt + 4 + + + pdbonly + true + ..\..\Target\Release\ + TRACE + prompt + 4 + + + + + False + ..\..\Components\log4net.dll + + + 3.0 + + + 3.0 + + + + 3.5 + + + + + + 3.5 + + + 3.5 + + + + + 3.0 + + + 3.0 + + + + + + + + + + ArtifactWall.xaml + + + SettingsNAboutUs.xaml + + + WorkspaceSelector.xaml + + + + WorkspaceSelector_DeleteWorkspacePage.xaml + + + WorkspaceSelector_NewWorkspacePage.xaml + + + WorkspaceSelector_RenameWorkspacePage.xaml + + + WorkspaceSelector_StandardPage.xaml + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618} + DataAccessLayer + + + {C1282050-455B-44F4-8520-1C005E38EFB2} + GUILib + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35} + WorkspaceMgr + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + $(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /unregister +$(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /tlb:$(TargetName).tlb /codebase +REM $(FrameworkDir)\regsvcs.exe /reconfig "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /appdir:"$(SolutionDir)target\$(ConfigurationName)" + + + \ No newline at end of file diff --git a/Client Services/GUIWPForms/GUIWPForms.csproj.bak b/Client Services/GUIWPForms/GUIWPForms.csproj.bak new file mode 100644 index 0000000..4cea55f --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms.csproj.bak @@ -0,0 +1,129 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {A02E052C-3C52-43DB-BB30-A47446B8165F} + Library + Properties + Foo.ClientServices.GUIWPForms + GUIWPForms + v3.5 + 512 + true + MyKeyFile.SNK + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + False + ..\..\Components\log4net.dll + + + 3.0 + + + 3.0 + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + 3.0 + + + 3.0 + + + + + + + + + ArtifactWall.xaml + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + MSBuild:Compile + Designer + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + copy "$(TargetDir)$(TargetFileName)" "$(SolutionDir)target\$(ConfigurationName)" /Y +copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)target\$(ConfigurationName)" /Y +$(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /unregister +$(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /tlb:$(TargetName).tlb /codebase +$(FrameworkDir)\regsvcs.exe /reconfig "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /appdir:"$(SolutionDir)target\$(ConfigurationName)" + + + \ No newline at end of file diff --git a/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml b/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml new file mode 100644 index 0000000..69cd747 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml.cs b/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml.cs new file mode 100644 index 0000000..455a4dd --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/ArtifactWall.xaml.cs @@ -0,0 +1,269 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Interop; +using System.Windows.Threading; +using System.Threading; + +using Foo.Platform; +using Foo.GUILib; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using System.Data; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for Window1.xaml + /// + public partial class ArtifactWall : Window + { + private bool m_bPerformanceCache = false; + + // Height and Width Settings + private int m_ItemHeight = 0; + private int m_ItemWidth = 0; + private int m_ImageHeight = 0; + private int m_ImageWidth = 0; + private int m_StackPanelHeight = 0; + private int m_StackPanelWidth = 0; + + // Hard-coded Settings + private const int ITEM_BORDER_THICKNESS = 2; + private const int SELECTION_BORDER_SIZE_MARGIN = 10; + + + // private DT holds all information needed for the DataGrid + public DataTable ArtifactsDT { get; private set; } + + //object CreateImage(string Path) + //{ + // Image myImage1 = new Image(); + // myImage1.Height = HEIGHT; + // myImage1.Width = WIDTH; + // BitmapImage myBitmapImage1 = new BitmapImage(); + // myBitmapImage1.BeginInit(); + // myBitmapImage1.UriSource = new Uri(Path); + // myBitmapImage1.DecodePixelHeight = HEIGHT; + // myBitmapImage1.DecodePixelWidth = WIDTH; + // myBitmapImage1.EndInit(); + // myImage1.Source = myBitmapImage1; + + // //myImage1.Margin = new Thickness(25); + // return myImage1; + //} + + Path CreatePath() + { + LineGeometry myLineGeometry = new LineGeometry(); + myLineGeometry.StartPoint = new Point(10, 50); + myLineGeometry.EndPoint = new Point(1600,50); + + Path myPath = new Path(); + myPath.Stroke = Brushes.Black; + myPath.StrokeThickness = 1; + myPath.Data = myLineGeometry; + return myPath; + } + + void AddWorkspaceArtifacts(string workspaceName) + { + //using (OoganizerState oogyState = new OoganizerState()) + //{ + // oogyState.SetCurrentWorkspace(workspaceName); + + // using (OoganizerAPIProxy proxy = oogyState.GetAPIProxy()) + // { + // Workspace workspace = proxy.API.GetWorkspace(workspaceName); + + // foreach (OoganizerDAL.Artifact artifact in workspace.Artifacts) + // { + // xamCarouselPanel1.ChildElements.Add(CreateImage(artifact.Snapshot_Path)); + // } + // } + //} + } + + private void CalculateHeightAndWidthSettings() + { + + // Image Settings + m_ImageHeight = 627; + m_ImageWidth = 400; + + // StackPanel Settings + const int STACK_PANEL_ITEMS_HEIGHT = 84; // add together the other StackPanel items + m_StackPanelHeight = m_ImageHeight + STACK_PANEL_ITEMS_HEIGHT; + m_StackPanelWidth = m_ImageWidth; + + // Item settings + m_ItemHeight = m_StackPanelHeight + SELECTION_BORDER_SIZE_MARGIN; + m_ItemWidth = m_StackPanelWidth + SELECTION_BORDER_SIZE_MARGIN; + } + + /// + /// + /// + /// + private void UpdateArtifactsWall(SortOrderForWorkspaces sortOrder) + { + // First Step - Clear the DT + ArtifactsDT.Rows.Clear(); + + // Second Step - Calculate Height/Width Settings + CalculateHeightAndWidthSettings(); + + // Third Step - Fill the DT with Artifact Information + ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsInTheSystem(SortOrderForArtifacts.MostFrequentlyAccessedAscending); + foreach (ArtifactItem artifact in artifacts) + { + var row = ArtifactsDT.NewRow(); + ArtifactsDT.Rows.Add(row); + + // Border Settings + row["BorderBrush"] = "Aqua"; + row["BorderThickness"] = ITEM_BORDER_THICKNESS; + + // StackPanel Settings + row["StackPanelHeight"] = m_StackPanelHeight; + row["StackPanelWidth"] = m_StackPanelWidth; + row["StackPanelBackground"] = "Transparent"; + + // Image Settings + row["ImagePath"] = artifact.SnapshotFile; + row["ImageHeight"] = m_ImageHeight; + row["ImageWidth"] = m_ImageWidth; + + // Artifact Information + if(artifact.IsFile) + row["Title"] = artifact.Name + " (" + artifact.FileName + ")"; + else if(artifact.IsUrl) + row["Title"] = artifact.Name + " (" + artifact.Location + ")"; + + row["LastLaunch"] = "Last Accessed: " + artifact.LastAccessed.ToString(); + row["FreqLaunch"] = "No. Times Accessed: " + artifact.AccessCounter.ToString(); + row["Notes"] = artifact.Note; + } + + // Third Step - Set xmlCarousel's Item Size + xamCarouselPanel1.ViewSettings.ItemSize = new Size(m_ItemWidth, m_ItemHeight); + + // Fourth Step - Set the number of items * we could change this later* + xamCarouselPanel1.ViewSettings.ItemsPerPage = 3; + + // Fifth Step - Refresh The xmlCarousel + xamCarouselPanel1.ItemsSource = ArtifactsDT.DefaultView; + } + + public ArtifactWall(bool bPerformanceCache) + { + InitializeComponent(); + + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowConstructor(this, bPerformanceCache)) + { + m_bPerformanceCache = true; + } + else + { + // Set Window Position Here + WindowState = WindowState.Maximized; + WindowStartupLocation = WindowStartupLocation.CenterScreen; + + xamCarouselPanel1.ViewSettings.ItemPath = CreatePath(); + xamCarouselPanel1.ViewSettings.ItemHorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; + xamCarouselPanel1.ViewSettings.ItemVerticalScrollBarVisibility = ScrollBarVisibility.Hidden; + xamCarouselPanel1.ViewSettings.AutoScaleItemContentsToFit = true; + xamCarouselPanel1.Focus(); + } + + //WindowInteropHelper hInter = new WindowInteropHelper(this); + //int width = System.Windows.Forms.Screen.FromHandle(hInter.Handle).Bounds.Width; + //int height = System.Windows.Forms.Screen.FromHandle(hInter.Handle).Bounds.Height; + } + + #region Page Events + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowOnLoad(this, m_bPerformanceCache)) + { + // Do anything you would like to load + } + else + { + // InitializeArtifactsDT + ArtifactsDT = new DataTable("ArtifactsData"); + + // Border Related Settings + ArtifactsDT.Columns.Add(new DataColumn("BorderBrush", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("BorderThickness", typeof(string))); + + // Image related Settings + ArtifactsDT.Columns.Add(new DataColumn("ImagePath", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("ImageHeight", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("ImageWidth", typeof(string))); + + // StackPanel Settings + ArtifactsDT.Columns.Add(new DataColumn("StackPanelHeight", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("StackPanelWidth", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("StackPanelBackground", typeof(string))); + + // Artifact Settings + ArtifactsDT.Columns.Add(new DataColumn("Title", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("LastLaunch", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("FreqLaunch", typeof(string))); + ArtifactsDT.Columns.Add(new DataColumn("Notes", typeof(string))); + + // + UpdateArtifactsWall(SortOrderForWorkspaces.Ascending); + } + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowClosing(this, m_bPerformanceCache)) + { + // Do anything you would like to load + } + else + { + + } + } + + #endregion + + # region Button Click Events + + private void btnClose_Click(object sender, RoutedEventArgs e) + { + this.Close(); + } + + private void btnUp_Click(object sender, RoutedEventArgs e) + { + + } + + private void btnDown_Click(object sender, RoutedEventArgs e) + { + + } + + #endregion + } +} + diff --git a/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml b/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml new file mode 100644 index 0000000..f2be67e --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + Auto-Hide Workspaces + + Auto-Save Office Documents + + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml.cs b/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml.cs new file mode 100644 index 0000000..90117ee --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/SettingsNAboutUs.xaml.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +using Foo.GUILib; +using Foo.Platform.Satellite; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// Interaction logic for SettingsNAboutUs.xaml + /// + public partial class SettingsNAboutUs : Window + { + private bool m_bPerformanceCache = false; + + public SettingsNAboutUs(bool bPerformanceCache) + { + InitializeComponent(); + + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowConstructor(this, bPerformanceCache)) + { + m_bPerformanceCache = true; + } + else + { + // Set Window Position Here + WindowStartupLocation = WindowStartupLocation.CenterScreen; + } + } + + #region Internationalization + + private void LoadAllTexts_Internationalization() + { + // Load Tab Headers + tabSettings.Header = GUIResx.GetString("TAB_SETTINGSNABOUTUS_SETTINGS"); + tabHelp.Header = GUIResx.GetString("TAB_SETTINGSNABOUTUS_HELP"); + tabAboutUs.Header = GUIResx.GetString("TAB_SETTINGSNABOUTUS_ABOUTUS"); + + // Load Group Labels + groupBoxWorkspaceSelector.Header = GUIResx.GetString("GROUPBOX_SETTINGABOUTUS_WORKSPACESELECTOR"); + groupBoxArtifactWall.Header = GUIResx.GetString("GROUPBOX_SETTINGABOUTUS_ARTIFACTWALL"); + + // Load Labels + + + + + } + + #endregion + + + #region Window Events + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowOnLoad(this, m_bPerformanceCache)) + { + + } + else + { + // Load Texts + LoadAllTexts_Internationalization(); + } + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowClosing(this, m_bPerformanceCache)) + { + + } + else + { + + } + } + + #endregion + + private void btnClose_Click(object sender, RoutedEventArgs e) + { + this.Close(); + } + } +} diff --git a/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml b/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml new file mode 100644 index 0000000..7e0fefe --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml.cs b/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml.cs new file mode 100644 index 0000000..c3deb69 --- /dev/null +++ b/Client Services/GUIWPForms/GUIWPForms/WorkspaceSelector.xaml.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using System.Windows.Interop; +using System.Reflection; +using System.Windows.Threading; + +using Foo.Platform; +using Foo.GUILib; + + +namespace Foo.ClientServices.GUIWPForms +{ + public enum ChildPages + { + WorkspaceSelector_StandardPage, + WorkspaceSelector_NewWorkspacePage, + WorkspaceSelector_RenameWorkspacePage, + WorkspaceSelector_DeleteWorkspacePage, + } + + /// + /// Interaction logic for WorkspaceSelector.xaml + /// + public partial class WorkspaceSelector : Window + { + private bool m_bPerformanceCache = false; + private Page[] m_ChildPages = null; + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + // Allow Childresn access to the Frame + public Frame WorkspaceSelectorFrm { get { return frmWorkspaceSelector; } } + + // Allow Children to overwrite MouseLeave Close Behavior + public bool DontCloseOnMouseLeave { get; set; } + + // Allow Children access to margin top/bottom + public int MarginTopBottom { get; set; } + + // internal flags + private bool m_bMouseFirstTimeEnter = false; + private bool m_bMouseHasEnteredBack = false; + private bool m_bMouseLeaveTimerCreated = false; + + /// + /// Child Page Creation Factory * should only be called internally * + /// + /// the page to instantiate + /// a new page object or null + private Page CreateChildPage(ChildPages page) + { + Page pageObj = null; + switch (page) + { + case ChildPages.WorkspaceSelector_NewWorkspacePage: + pageObj = new WorkspaceSelector_NewWorkspacePage(m_bPerformanceCache); + break; + + case ChildPages.WorkspaceSelector_RenameWorkspacePage: + pageObj = new WorkspaceSelector_RenameWorkspacePage(m_bPerformanceCache); + break; + + case ChildPages.WorkspaceSelector_DeleteWorkspacePage: + pageObj = new WorkspaceSelector_DeleteWorkspacePage(m_bPerformanceCache); + break; + + case ChildPages.WorkspaceSelector_StandardPage: + pageObj = new WorkspaceSelector_StandardPage(m_bPerformanceCache); + break; + } + return pageObj; + } + + /// + /// Use this to actually navigate to a child page object on the WorkspaceSelector + /// + /// a page to navigate to + public void NavigateToChildPage(ChildPages page) + { + try + { + Page pageObj = CreateChildPage(page); + if (pageObj != null) + { + pageObj.Tag = this; // pass out this object + if (!frmWorkspaceSelector.Navigate(pageObj)) + Log.Info(string.Format("{0}() - WorkspaceSelector could not navigate to ChildPage {1}", MethodBase.GetCurrentMethod().Name, (int)page)); + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Thrown", MethodBase.GetCurrentMethod().Name, e)); + } + } + + /// + /// WorkspaceSelector Constructor - set's default values for the object + /// Instantiates all child pages when in Performance Mode + /// + /// true if this is a cached form for performance, false every other time + public WorkspaceSelector(bool bPerformanceCache) + { + InitializeComponent(); + + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowConstructor(this, bPerformanceCache)) + { + m_bPerformanceCache = true; + + // Performance Load the Child Pages as well + int n = Enum.GetValues(typeof(ChildPages)).Length; + m_ChildPages = new Page[n]; + + // Iterate thru enums and create the corresponding objects in the Cache + for (int i = 0; i < n; ++i) + { + ChildPages page = (ChildPages)Enum.ToObject(typeof(ChildPages), i); + m_ChildPages[i] = CreateChildPage(page); + } + } + + // By default allow mouse leave to close the form + DontCloseOnMouseLeave = false; + + // MarginTopBottom is the space up and below the frame 2 * 6 = 12 (but we want 2 pixels trimmed) + MarginTopBottom = 10; + } + + #region Window Events + + /// + /// Window Load Event - Hook into MessageHook if in performance mode, + /// otherwise load default child + /// + private void Window_Loaded(object sender, RoutedEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowOnLoad(this, m_bPerformanceCache)) + { + // To Anything her you may want to do + } + else + { + // Navigate to the Default Page + NavigateToChildPage(ChildPages.WorkspaceSelector_StandardPage); + + // Set the GUI State to this object + GUIState.CurrentlyShowingWPFWindow = this; + + // Start the Load Mouse Enter Timer for 1.5 seconds + DispatcherTimer dispatcherTimer = new DispatcherTimer(); + dispatcherTimer.Tick += new EventHandler(dispatcherTimerOnLoadMouseEnter_Tick); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 500); + dispatcherTimer.Start(); + } + } + + /// + /// keep track of window closed + /// + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + // * For Performance Caching * + if (WPFHiddenWindow.HiddenWindowClosing(this, m_bPerformanceCache)) + { + // To Anything her you may want to do + } + else + { + // Set the GUI State to this object + GUIState.CurrentlyShowingWPFWindow = null; + } + } + + /// + /// Keep track of mouse enter + /// + private void Window_MouseEnter(object sender, MouseEventArgs e) + { + m_bMouseFirstTimeEnter = true; + m_bMouseHasEnteredBack = true; + } + + /// + /// General Standard behavior - Close the form on Mouse Leave, except when + /// children overwrite this behavior via DontCloseOnMouseLeave + /// + private void Window_MouseLeave(object sender, MouseEventArgs e) + { + m_bMouseHasEnteredBack = false; + if (!m_bMouseLeaveTimerCreated) + { + // Start Mouse Leave Timer for 1.5 seconds + DispatcherTimer dispatcherTimer = new DispatcherTimer(); + dispatcherTimer.Tick += new EventHandler(dispatcherTimerMouseLeave_Tick); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 500); + dispatcherTimer.Start(); + + // Set flag + m_bMouseLeaveTimerCreated = true; + } + } + + #endregion + + /// + /// Run One Time - after Mouse Leaves. Closes Form if Mouse has not entered + /// + void dispatcherTimerMouseLeave_Tick(object sender, EventArgs e) + { + // Turn off the timer + DispatcherTimer dispatcherTimer = (DispatcherTimer)sender; + dispatcherTimer.Stop(); + m_bMouseLeaveTimerCreated = false; + + // Close this window, but only if the mouse has not entered back || + // we are told not to do it + if (!m_bMouseHasEnteredBack && !DontCloseOnMouseLeave) + this.Close(); + } + + /// + /// Run One Time - Upon Load. Closes form if mouse has not entered + /// + void dispatcherTimerOnLoadMouseEnter_Tick(object sender, EventArgs e) + { + // We only want to run this timer Once * Always * + DispatcherTimer dispatcherTimer = (DispatcherTimer)sender; + dispatcherTimer.Stop(); + + // Close this window, but only if the mouse has not entered back + // Close this Form *always* + if (!m_bMouseFirstTimeEnter && !DontCloseOnMouseLeave) + this.Close(); + } + + } +} diff --git a/Client Services/GUIWPForms/IGUIWPForms.cs b/Client Services/GUIWPForms/IGUIWPForms.cs new file mode 100644 index 0000000..ea6875a --- /dev/null +++ b/Client Services/GUIWPForms/IGUIWPForms.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace Foo.ClientServices.GUIWPForms +{ + /// + /// GUIPWPForms uses IGUIPWPForms Interface. It exposes functions to external + /// callers regarding the type of GUIWPForms we can launch. + /// ~Most functions require an hWnd which is the DeskbandButton to properly Position the form. + /// ~However if hWnd is Zero and we are in Debug we just center it. * For Debugging Purpose * + /// + [Guid("652DDE0A-D3FA-4525-8272-1616127819D2")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + [ComVisible(true)] + public interface IGUIPWPForms + { + // ArtifactWall + bool LaunchArtifactWall(IntPtr hDeskbandButtonWnd); + bool CloseArtifactWall(); + + // WorkspaceSelector + bool LaunchWorkspaceSelector(IntPtr hDeskbandButtonWnd); + bool CloseWorkspaceSelector(); + + // Settings N' About Us Page + bool LaunchSettingsNAboutUs(IntPtr hDeskbandButtonWnd); + bool CloseSettingsNAboutUs(); + } +} diff --git a/Client Services/GUIWPForms/MyKeyFile.SNK b/Client Services/GUIWPForms/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Client Services/GUIWPForms/MyKeyFile.SNK differ diff --git a/Client Services/GUIWPForms/Properties/AssemblyInfo.cs b/Client Services/GUIWPForms/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8a9f4bf --- /dev/null +++ b/Client Services/GUIWPForms/Properties/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; +using System.EnterpriseServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GUIWPForms")] +[assembly: AssemblyDescription("Performance Caching for GUIWPForms")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Ooganizer Corporation")] +[assembly: AssemblyProduct("GUIWPForms")] +[assembly: AssemblyCopyright("Copyright © Ooganizer Corporation 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(true)] +[assembly: ApplicationID("E6A84616-5ED1-4679-B26D-64F80A5E41CD")] +[assembly: ApplicationActivation(ActivationOption.Server)] +[assembly: ApplicationAccessControl(Value = false, Authentication = AuthenticationOption.None)] +[assembly: ApplicationName("Foo.ClientServices")] +[assembly: Description("Provides Data Access and Performance Caching for Ooganizer Components")] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Client Services/GUIWPForms/Properties/Resources.Designer.cs b/Client Services/GUIWPForms/Properties/Resources.Designer.cs new file mode 100644 index 0000000..2a780dd --- /dev/null +++ b/Client Services/GUIWPForms/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.ClientServices.GUIWPForms.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.ClientServices.GUIWPForms.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Client Services/GUIWPForms/Properties/Resources.resx b/Client Services/GUIWPForms/Properties/Resources.resx new file mode 100644 index 0000000..85c9090 --- /dev/null +++ b/Client Services/GUIWPForms/Properties/Resources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Client Services/GUIWPForms/Properties/Settings.Designer.cs b/Client Services/GUIWPForms/Properties/Settings.Designer.cs new file mode 100644 index 0000000..d100d52 --- /dev/null +++ b/Client Services/GUIWPForms/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.ClientServices.GUIWPForms.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Client Services/GUIWPForms/Properties/Settings.settings b/Client Services/GUIWPForms/Properties/Settings.settings new file mode 100644 index 0000000..15034e7 --- /dev/null +++ b/Client Services/GUIWPForms/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/Client Services/GUIWPForms/Properties/licenses.licx b/Client Services/GUIWPForms/Properties/licenses.licx new file mode 100644 index 0000000..e8ba8ea --- /dev/null +++ b/Client Services/GUIWPForms/Properties/licenses.licx @@ -0,0 +1 @@ +Infragistics.Windows.Controls.XamCarouselListBox, Infragistics3.Wpf.v8.2, Version=8.2.20082.1002, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb diff --git a/Components/log4net.dll b/Components/log4net.dll new file mode 100644 index 0000000..ffc57e1 Binary files /dev/null and b/Components/log4net.dll differ diff --git a/DataAccessLayer/DB.cs b/DataAccessLayer/DB.cs new file mode 100644 index 0000000..248a863 --- /dev/null +++ b/DataAccessLayer/DB.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Data; +using System.Data.SqlServerCe; +using System.Text; +using System.IO; +using System.Resources; +using System.Reflection; + +namespace Foo.DataAccessLayer +{ + public class DB + { + /// + /// Private Properties + /// + private static string _dbPath = "C:\\_ROOT_\\TestANizer\\DataAccessLayer"; + private static string _dbName = "OggyNize.sdf"; + private static string _dbPassword = "1kso123!~~!@"; + private static string _connString { get { return String.Format("Data Source={0}\\{1}; encryption mode=platform default; Password=\"{2}\"; Encrypt = TRUE;", Path.GetFullPath(_dbPath), _dbName, _dbPassword); } } + + /// + /// Public Properties + /// + public static bool DoesDBExist { get { return (File.Exists(_dbPath + "\\" + _dbName)); } } + + /// + /// Use this to create the Default Database + /// + public static void CreateDefaultDB() + { + CreateDB(_dbPath, _dbName, _dbPassword); + } + + /// + /// Use this to delete the Default Database + /// + public static void DeleteDefaultDB() + { + if (!String.IsNullOrEmpty(_dbPath) && + !String.IsNullOrEmpty(_dbName) && + Directory.Exists(_dbPath) && + File.Exists(_dbPath + "\\" + _dbName)) + { + File.Delete(_dbPath + "\\" + _dbName); + } + } + + /// + /// Use this function to create a New Database, if it doesn't already exist + /// + /// Path to the Database + /// Name of the Database + /// Password to use on the Database + internal static void CreateDB(string dbPath, string dbName, string dbPassword) + { + try + { + if (dbPath.Length > 3 && dbPath[dbPath.Length - 1] == '\\') + dbPath = dbPath.Remove(dbPath.Length - 1); + + if (!String.IsNullOrEmpty(dbName) && !dbName.ToLower().Contains(".sdf")) + dbName = dbName + ".sdf"; + + if (!String.IsNullOrEmpty(dbPath) && + !String.IsNullOrEmpty(dbName) && + Directory.Exists(dbPath) && + !File.Exists(dbPath + "\\" + dbName)) + { + _dbPath = dbPath; + _dbName = dbName; + _dbPassword = dbPassword; + using (SqlCeEngine engine = new SqlCeEngine(_connString)) + { + engine.CreateDatabase(); + } + + // This will now Construct all the necessary Tables + // we need ~very nice and automatic + CreateInitialDBTables(); + } + } + catch (Exception) { /* ignore */ } + } + + /// + /// Responsible for creating all the initial Tables for the database + /// + private static void CreateInitialDBTables() + { + foreach (string TableResourceName in ResourceHelper.GetTableResourceNames()) + { + string strSQL = ResourceHelper.GetTextSqlFromResourceFile(TableResourceName); + string[] strCommands = strSQL.Split(';'); + + foreach (string strCommand in strCommands) + { + // Is there a Label + if (strCommand.Contains(':')) + { + string[] strLabelAndCommand = strCommand.Split(':'); + string strLabel = strLabelAndCommand[0]; + string strCommand2 = strLabelAndCommand[1]; + + // Save the Label in the Version Map + string strTableName = ResourceHelper.GetTableNameFromTableResourceName(TableResourceName); + ResourceHelper.s_VersioningTablesMap[strTableName] = strLabel; + + // Run the Command + RunSQLCommandTextExecuteNonQuery(strCommand2.Trim()); + } + else + { + RunSQLCommandTextExecuteNonQuery(strCommand.Trim()); + } + } + } + + // Now that all Tables are created, we can now save the VersionMap into the Database + dVersioningTables versionTable = new dVersioningTables(); + foreach (string key in ResourceHelper.s_VersioningTablesMap.Keys) + versionTable.AddUpdateVersionInformationForSpecifiedTable(key, ResourceHelper.s_VersioningTablesMap[key]); + } + + /// + /// Use this to Run SQL with the ExecuteNonQuery() Command Object + /// + /// SQL Text/Commands to execute + /// the result of the ExecuteNonQuery() operation + internal static int RunSQLCommandTextExecuteNonQuery(string SqlCommandText) + { + int nResult = -1; + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = SqlCommandText; + nResult = cmd.ExecuteNonQuery(); + } + } + } + catch (Exception) { /* ignore */ } + return nResult; + } + + /// + /// Use this to Run SQL with the ExecuteNonQuery() Command Object + /// + /// SQL Text/Commands to execute + /// Allows the use of sql parameters + /// the result of the ExecuteNonQuery() operation + internal static int RunSQLCommandTextExecuteNonQuery(string SqlCommandText, SqlCeParameter[] parameters) + { + int nResult = -1; + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = SqlCommandText; + foreach (SqlCeParameter parameter in parameters) + cmd.Parameters.Add(parameter); + nResult = cmd.ExecuteNonQuery(); + } + } + } + catch (Exception) { /* ignore */ } + return nResult; + } + + /// + /// Use this to Run SQL with the ExecuteScalar() Command Object + /// + /// SQL Text/Commands to execute + /// the result of the ExecuteScalar() operation + internal static object RunSQLCommandTextExecuteScalar(string SqlCommandText) + { + object oResult = null; + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = SqlCommandText; + oResult = cmd.ExecuteScalar(); + } + } + } + catch (Exception) { /* ignore */ } + + // Try Parsing the oResult, if an error occurs return null + try + { + if (String.IsNullOrEmpty(oResult.ToString())) + oResult = null; + } + catch (Exception) { oResult = null; } + return oResult; + } + + /// + /// Use this to Run SQL with the ExecuteScalar() Command Object + /// + /// SQL Text/Commands to execute + /// Allows the use of sql parameters + /// the result of the ExecuteScalar() operation + internal static object RunSQLCommandTextExecuteScalar(string SqlCommandText, SqlCeParameter[] parameters) + { + object oResult = null; + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = SqlCommandText; + foreach (SqlCeParameter parameter in parameters) + cmd.Parameters.Add(parameter); + oResult = cmd.ExecuteScalar(); + } + } + } + catch (Exception) { /* ignore */ } + + // Try Parsing the oResult, if an error occurs return null + try + { + if (String.IsNullOrEmpty(oResult.ToString())) + oResult = null; + } + catch (Exception) { oResult = null; } + return oResult; + } + + /// + /// Use this to Run SQL with the DataAdapter Fill() + /// + /// SQL Text to execute + /// the result of the DataAdapter Fill() operation + internal static DataSet RunSQLTextFillDataSet(string SqlText) + { + DataSet dataset = new DataSet(); + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeDataAdapter dataAdapter = new SqlCeDataAdapter(SqlText, conn)) + { + dataAdapter.Fill(dataset); + } + } + } + catch (Exception) { /* ignore */ } + return dataset; + } + + /// + /// Use this to Run SQL with the DataAdapter Fill() + /// + /// SQL Text to execute + /// Allows the use of sql parameters + /// the result of the DataAdapter Fill() operation + internal static DataSet RunSQLTextFillDataSet(string SqlText, SqlCeParameter[] parameters) + { + DataSet dataset = new DataSet(); + try + { + using (SqlCeConnection conn = new SqlCeConnection(_connString)) + { + conn.Open(); + using (SqlCeCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = SqlText; + foreach (SqlCeParameter parameter in parameters) + cmd.Parameters.Add(parameter); + + using (SqlCeDataAdapter dataAdapter = new SqlCeDataAdapter(cmd)) + { + dataAdapter.Fill(dataset); + } + } + } + } + catch (Exception) { /* ignore */ } + return dataset; + } + } +} diff --git a/DataAccessLayer/Data.cs b/DataAccessLayer/Data.cs new file mode 100644 index 0000000..86d1b84 --- /dev/null +++ b/DataAccessLayer/Data.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.DataAccessLayer +{ + public class Data + { + /// + /// Public Properties + /// + public static dArtifacts Artifacts { get { return _artifacts; } } + public static dWorkspace Workspace { get { return _workspace; } } + public static dState State { get { return _state; } } + public static dUserSettings UserSettings { get { return _UserSettings; } } + + /// + /// Internal Properties + /// + internal static dVersioningTables VersioningTables { get { return _VersioningTables; } } + + /// + /// Private Locations for above Properties + /// + private static dArtifacts _artifacts; + private static dWorkspace _workspace; + private static dState _state; + private static dVersioningTables _VersioningTables; + private static dUserSettings _UserSettings; + + static Data() + { + // Upon First Instantiation of Data, + // ensure that the Default DB Exists + DB.CreateDefaultDB(); + + // Load All Public Data Types + _artifacts = new dArtifacts(); + _workspace = new dWorkspace(); + _state = new dState(); + _UserSettings = new dUserSettings(); + + // Load All Internal Data Types + _VersioningTables = new dVersioningTables(); + } + } +} diff --git a/DataAccessLayer/DataAccessLayer.csproj b/DataAccessLayer/DataAccessLayer.csproj new file mode 100644 index 0000000..8c84f88 --- /dev/null +++ b/DataAccessLayer/DataAccessLayer.csproj @@ -0,0 +1,224 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618} + Library + Properties + Foo.DataAccessLayer + DataAccessLayer + v3.5 + 512 + true + MyKeyFile.SNK + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + + + + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DataAccessLayer/DataTypes.cs b/DataAccessLayer/DataTypes.cs new file mode 100644 index 0000000..3af222e --- /dev/null +++ b/DataAccessLayer/DataTypes.cs @@ -0,0 +1,564 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Data.SqlTypes; +using System.Data; + +namespace Foo.DataAccessLayer.DataTypes +{ + // ArtifactTypes + public enum ArtifactTypes + { + File, + Url + } + + // Artifacts + public enum SortOrderForArtifacts + { + None, + Ascending, + Descending, + LocationAscending, + LocationDescending, + LastAccessedAscending, + LastAccessedDescending, + MostFrequentlyAccessedAscending, + MostFrequentlyAccessedDescending + } + + // Workspaces + public enum SortOrderForWorkspaces + { + None, + Ascending, + Descending, + LastAccessedAscending, + LastAccessedDescending, + MostFrequentlyAccessedAscending, + MostFrequentlyAccessedDescending + } + + /// + /// This class holds the SortOrder Helper SQL functions for the SortOrder Enums listed above + /// + public class SortOrderSQLHelpers + { + /// + /// Use this to create the OrderBy Clause for the Workspace SortOrder Function + /// + /// sql string to add sortOrder to + /// the Workspace SortOrder Enum + /// modified SQL String + public static string SortOrderForArtifactsHelper(string sql, SortOrderForArtifacts sortOrder) + { + switch (sortOrder) + { + case SortOrderForArtifacts.None: + break; + + case SortOrderForArtifacts.Ascending: + sql = sql + " ORDER BY [Artifacts].[Name] ASC"; + break; + + case SortOrderForArtifacts.Descending: + sql = sql + " ORDER BY [Artifacts].[Name] DESC"; + break; + + case SortOrderForArtifacts.LastAccessedAscending: + sql = sql + " ORDER BY [Artifacts].[LastAccessed] ASC"; + break; + + case SortOrderForArtifacts.LastAccessedDescending: + sql = sql + " ORDER BY [Artifacts].[LastAccessed] DESC"; + break; + + case SortOrderForArtifacts.LocationAscending: + sql = sql + " ORDER BY [Artifacts].[Location] ASC"; + break; + + case SortOrderForArtifacts.LocationDescending: + sql = sql + " ORDER BY [Artifacts].[Location] DESC"; + break; + + case SortOrderForArtifacts.MostFrequentlyAccessedAscending: + sql = sql + " ORDER BY [Artifacts].[AccessCounter] ASC"; + break; + + case SortOrderForArtifacts.MostFrequentlyAccessedDescending: + sql = sql + " ORDER BY [Artifacts].[AccessCounter] DESC"; + break; + } + return sql; + } + + /// + /// Use this to create the OrderBy Clause for the Workspace SortOrder Function + /// + /// sql string to add sortOrder to + /// the Workspace SortOrder Enum + /// modified SQL String + public static string SortOrderForWorkspacesHelper(string sql, SortOrderForWorkspaces sortOrder) + { + switch (sortOrder) + { + case SortOrderForWorkspaces.None: + break; + + case SortOrderForWorkspaces.Ascending: + sql = sql + " ORDER BY [Workspaces].[Name] ASC"; + break; + + case SortOrderForWorkspaces.Descending: + sql = sql + " ORDER BY [Workspaces].[Name] DESC"; + break; + + case SortOrderForWorkspaces.LastAccessedAscending: + sql = sql + " ORDER BY [Workspaces].[LastAccessed] ASC"; + break; + + case SortOrderForWorkspaces.LastAccessedDescending: + sql = sql + " ORDER BY [Workspaces].[LastAccessed] DESC"; + break; + + case SortOrderForWorkspaces.MostFrequentlyAccessedAscending: + sql = sql + " ORDER BY [Workspaces].[AccessCounter] ASC"; + break; + + case SortOrderForWorkspaces.MostFrequentlyAccessedDescending: + sql = sql + " ORDER BY [Workspaces].[AccessCounter] DESC"; + break; + } + return sql; + } + } + + /// + /// Validation Classes + /// + public class DataTypeValidation + { + /// + /// Checks the logistics of the WorkspaceName (not the DB) + /// + /// true if valid logistically, false otherwise + public static bool IsValidWorkspaceName(string WorkspaceName) + { + if ((String.IsNullOrEmpty(WorkspaceName)) || + (WorkspaceName.Length < 1) || + (WorkspaceName.Length > 75)) + return false; + else + return true; + } + + /// + /// Use this to check the return of an ArtifactItemGroup + /// + /// ArtifactGroup + /// true if ArtifactItemGroup is Empty, false otherwise + public static bool IsEmptyArtifactItemGroup(ArtifactItem[] artifactItems) + { + if ((artifactItems.Length == 1) && !artifactItems[0].IsLocationValid) + return true; + else + return false; + } + + /// + /// Use this to check the return of an WorkspaceItemGroup + /// + /// WorkspaceItemGroup + /// true if WorkspaceItemGroup is Empty, false otherwise + public static bool IsEmptyWorkspaceItemGroup(WorkspaceItem[] workspaceItems) + { + if ((workspaceItems.Length == 1) && !workspaceItems[0].IsValid) + return true; + else + return false; + } + + /// + /// Uset this for quick and easy DataSet Validation + /// + /// a dataset object + /// true if dataset is empty, false otherwise + public static bool IsEmptyDataSet(DataSet dataset) + { + if ((dataset == null) || + (dataset.Tables.Count == 0) || + ((dataset.Tables.Count == 1) && (dataset.Tables[0].Rows.Count <= 0))) + { + return true; + } + return false; + } + + /// + /// For internal use only - Check if the TableName entered is Valid + /// + /// a table name + /// true if valid logistically, false otherwise + internal static bool IsValidTableName(string TableName) + { + if ((String.IsNullOrEmpty(TableName)) || + (TableName.Length < 1) || + (TableName.Length > 75)) + return false; + else + return true; + } + + /// + /// For internal use only - Check to see if Version information is valid + /// + /// Version Information for a table + /// true if valid logistically, false otherwise + internal static bool IsValidVersionInformation(string VersionInformation) + { + bool bIsValid = (!String.IsNullOrEmpty(VersionInformation) && (VersionInformation.Length == 8)); + if (bIsValid) + { + string[] versionEntities = VersionInformation.Split('.'); + bIsValid = (versionEntities.Length == 3); + } + return (bIsValid); + } + } + + /// + /// Helper Classes + /// + public class DataTypeHelpers + { + /// + /// Many Artifact Checking Functions (Except for Insert/modify) Only need the location, + /// So if you have a location, use this function to create a quick Artifact to use in those + /// checking functions + /// + /// + /// + public static ArtifactItem CreateLocationOnlyArtifact(string location) + { + ArtifactItem artifactItem = new ArtifactItem() + { + Location = location + }; + return artifactItem; + } + + /// + /// Use this to create an empty ArtifactItemGroup (should only be used internally) + /// + /// An Empty ArtifactItemGroups + internal static ArtifactItem[] EmptyArtifactItemGroup() + { + ArtifactItem[] artifactItems = new ArtifactItem[] { new ArtifactItem() { Location = "" } }; + return artifactItems; + } + + /// + /// Use this to create an empty WorkspaceItemGroup (should only be used internally) + /// + /// An Empty WorkspaceItemGroups + internal static WorkspaceItem[] EmptyWorkspaceItemGroup() + { + WorkspaceItem[] workspaceItems = new WorkspaceItem[] { new WorkspaceItem() { Name = "" } }; + return workspaceItems; + } + + } + + /// + /// Use this class for some of our Workspace Methods. Holds Workspace Information as well + /// as performs Validation. + /// + public class WorkspaceItem + { + public string Name { get; set; } + public DateTime LastAccessed { get; private set; } + public int AccessCounter { get; set; } + + // Needed to make sure that dateTime is within limits of SQL, + // Otherwise SQL stmt may generate an error + public bool SetLastAccessed(DateTime dateTime) + { + if (dateTime >= SqlDateTime.MinValue.Value && + dateTime <= SqlDateTime.MaxValue.Value) + { + LastAccessed = dateTime; + return true; + } + return false; + } + + // *Custom Tag Property * To be used by Callers to tag the object + public string Tag { get; set; } + + // default + public WorkspaceItem() + { + Name = ""; + LastAccessed = SqlDateTime.MinValue.Value; + AccessCounter = 0; + + // Tag + Tag = ""; + } + + /// + /// Performs basic Type Validity Tests + /// + public bool IsValid + { + get + { + if ((Name.Length > 1) && + (Name.Length <= 75) && + (AccessCounter >= 0) && + (LastAccessed != SqlDateTime.MinValue.Value) + ) + { + return true; + } + else + { + return false; + } + } + } + + #region ICloneable Members + public object Clone() + { + return this.MemberwiseClone(); + } + #endregion + } + + /// + /// Use this Class for all our Artifact Methods. Holds Artifact Information as well + /// as performs Validation. Use IsValidFileIntegrity() for IO validation + /// + public class ArtifactItem : ICloneable + { + public String Name { get; set; } + public ArtifactTypes Type { get; set; } + public String Location { get; set; } + public String Note { get; set; } + public String SnapshotFile { get; set; } + public DateTime LastAccessed { get; private set; } + public int AccessCounter { get; set; } + + // Needed to make sure that dateTime is within limits of SQL, + // Otherwise SQL stmt may generate an error + public bool SetLastAccessed(DateTime dateTime) + { + if (dateTime >= SqlDateTime.MinValue.Value && + dateTime <= SqlDateTime.MaxValue.Value) + { + LastAccessed = dateTime; + return true; + } + return false; + } + + // default + public ArtifactItem() + { + SetAsFileType(); + Name = ""; + Location = ""; + Note = ""; + SnapshotFile = ""; + + // LinkProperties + WindowTop = 0; + WindowLeft = 0; + WindowHeight = 0; + WindowWidth = 0; + + // Access properties + LastAccessed = SqlDateTime.MinValue.Value; + AccessCounter = 0; + + // Tag + Tag = ""; + } + + // Type Check + public bool IsUrl { get { return Type == ArtifactTypes.Url; } } + public bool IsFile { get { return Type == ArtifactTypes.File; } } + + // Type Helpers + public string FileName + { + get + { + if (IsFile) + { + int nIndex = Location.LastIndexOf('\\'); + if (nIndex > 0 && nIndex < Location.Length) + return Location.Substring((nIndex + 1)); + } + return String.Empty; + } + } + public string FileLocation + { + get + { + if (IsFile) + { + int nIndex = Location.LastIndexOf('\\'); + if (nIndex > 0 && nIndex < Location.Length) + return Location.Substring(0,nIndex); + } + return String.Empty; + } + } + + // Type Setting + public void SetAsFileType() { Type = ArtifactTypes.File; } + public void SetAsUrlType() { Type = ArtifactTypes.Url; } + public bool SetType(string strType) + { + if (strType.ToUpper() == "FILE") + { + SetAsFileType(); + return true; + } + else if (strType.ToUpper() == "URL") + { + SetAsUrlType(); + return true; + } + else + { + return false; + } + } + + // Setters + public bool SetFile(string fileNameAndLocation) + { + if ((fileNameAndLocation.Length > 1) && File.Exists(fileNameAndLocation)) + { + SetAsFileType(); + Location = fileNameAndLocation; + return true; + } + return false; + } + public bool SetUrl(string Url) + { + if ((Url.Length > 1)) // To Do - Better Url Checking + { + SetAsUrlType(); + Location = Url; + return true; + } + return false; + } + + // *Custom Tag Property * To be used by Callers to tag the object + public string Tag { get; set; } + + /// + /// This Information is used by the link in the Workspace. + /// ~This information is only filed in the artifact when being retrieved + /// from a workspace which has link information + /// + public int WindowTop { get; set; } + public int WindowLeft { get; set; } + public int WindowHeight { get; set; } + public int WindowWidth { get; set; } + + /// + /// Use this function to do proper validation of the Link Properties + /// + public bool AreWorkspaceLinkPropertiesValid + { + get + { + if ((WindowHeight > 0) && + (WindowWidth > 0)) + return true; + else + return false; + } + } + + /// + /// Performs basic Type Validity Tests + /// + public bool IsValid + { + get + { + if((Name.Length > 1) && + (Name.Length <= 150) && + (Location.Length > 1) && + (Location.Length <= 300) && + (Note.Length <= 3000) && + (SnapshotFile.Length > 1) && + (SnapshotFile.Length <= 300) && + (AccessCounter >= 0) //&& + //(LastAccessed != SqlDateTime.MinValue.Value) + ) + { + return true; + } + else + { + return false; + } + } + } + + /// + /// Since Artifact Location is our main source of determining + /// existence (this provides an easy check only for valid location) + /// + public bool IsLocationValid + { + get + { + if ((Location.Length > 1) && + (Location.Length <= 300)) + return true; + else + return false; + } + } + + /// + /// Performs Advanced File Validity Tests + /// + public bool IsValidFileIntegrity + { + get + { + if (IsFile && !File.Exists(Location)) + return false; + + // To Do * Check if is Valid Url * + + if (!File.Exists(SnapshotFile)) + return false; + + return true; + } + } + + #region ICloneable Members + public object Clone() + { + return this.MemberwiseClone(); + } + #endregion + } + +} diff --git a/DataAccessLayer/MyKeyFile.SNK b/DataAccessLayer/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/DataAccessLayer/MyKeyFile.SNK differ diff --git a/DataAccessLayer/Properties/AssemblyInfo.cs b/DataAccessLayer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d1bc0a6 --- /dev/null +++ b/DataAccessLayer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DataAccessLayer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DataAccessLayer")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4eac069e-728a-48b2-989e-0be548d211ef")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DataAccessLayer/Properties/Resources.Designer.cs b/DataAccessLayer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7458a06 --- /dev/null +++ b/DataAccessLayer/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.DataAccessLayer.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.DataAccessLayer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/DataAccessLayer/Properties/Resources.resx b/DataAccessLayer/Properties/Resources.resx new file mode 100644 index 0000000..5ea0895 --- /dev/null +++ b/DataAccessLayer/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DataAccessLayer/Properties/Settings.Designer.cs b/DataAccessLayer/Properties/Settings.Designer.cs new file mode 100644 index 0000000..d7fe635 --- /dev/null +++ b/DataAccessLayer/Properties/Settings.Designer.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.DataAccessLayer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)] + [global::System.Configuration.DefaultSettingValueAttribute("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\TestData\\Files\\DupF" + + "iles2\\DatabaseBills.accdb;Persist Security Info=True")] + public string DatabaseBillsConnectionString { + get { + return ((string)(this["DatabaseBillsConnectionString"])); + } + } + } +} diff --git a/DataAccessLayer/Properties/Settings.settings b/DataAccessLayer/Properties/Settings.settings new file mode 100644 index 0000000..cf1ae0b --- /dev/null +++ b/DataAccessLayer/Properties/Settings.settings @@ -0,0 +1,14 @@ + + + + + + <?xml version="1.0" encoding="utf-16"?> +<SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <ConnectionString>Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TestData\Files\DupFiles2\DatabaseBills.accdb;Persist Security Info=True</ConnectionString> + <ProviderName>System.Data.OleDb</ProviderName> +</SerializableConnectionString> + Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TestData\Files\DupFiles2\DatabaseBills.accdb;Persist Security Info=True + + + \ No newline at end of file diff --git a/DataAccessLayer/ResourceHelper.cs b/DataAccessLayer/ResourceHelper.cs new file mode 100644 index 0000000..ac9adf3 --- /dev/null +++ b/DataAccessLayer/ResourceHelper.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.IO; +using System.Collections.Specialized; + +namespace Foo.DataAccessLayer +{ + class ResourceHelper + { + // Used by DB to keep track of labels and Versioning + public static StringDictionary s_VersioningTablesMap = new StringDictionary(); + + /// + /// Get All Sql Table Resource Names + /// + /// + public static string[] GetTableResourceNames() + { + List tableResources = new List(); + + string[] resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); + foreach (string ResourceName in resourceNames) + { + if(ResourceName.Contains("DataAccessLayer.Sql.Tables.")) + tableResources.Add(ResourceName); + } + + return tableResources.ToArray(); + } + + /// + /// Gives you just the Table Name without the Resource string before and after + /// + /// a table Resource name + /// the table name + public static string GetTableNameFromTableResourceName(string TableResouceName) + { + // First trim the sqlce + TableResouceName = TableResouceName.Replace(".sqlce", ""); + + // Now find the last dot and trim from there + int index = TableResouceName.LastIndexOf('.'); + return TableResouceName.Substring(index + 1); + } + + /// + /// Get the Text/SQL String from a specified ResourceFileName + /// + /// a specific ResourceFileName + /// + public static string GetTextSqlFromResourceFile(string resourceFileName) + { + StreamReader stream = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFileName)); + if (stream != null) + { + string strText = stream.ReadToEnd(); + strText = strText.Replace('\r', ' '); + strText = strText.Replace('\n', ' '); + return strText; + } + else + return string.Empty; + } + } +} diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Albin likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles1/Albin likes apples.doc new file mode 100644 index 0000000..07ad7bc Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Albin likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book1.xls b/DataAccessLayer/TestData/Files/DupFiles1/Book1.xls new file mode 100644 index 0000000..c851022 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book1.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book1.xlsx b/DataAccessLayer/TestData/Files/DupFiles1/Book1.xlsx new file mode 100644 index 0000000..150de4a Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book1.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book2.xls b/DataAccessLayer/TestData/Files/DupFiles1/Book2.xls new file mode 100644 index 0000000..1d776a4 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book2.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book2.xlsx b/DataAccessLayer/TestData/Files/DupFiles1/Book2.xlsx new file mode 100644 index 0000000..715c15d Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book2.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book3.xls b/DataAccessLayer/TestData/Files/DupFiles1/Book3.xls new file mode 100644 index 0000000..82831c1 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book3.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Book4.xls b/DataAccessLayer/TestData/Files/DupFiles1/Book4.xls new file mode 100644 index 0000000..cfb1128 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Book4.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/DatabaseBills.accdb b/DataAccessLayer/TestData/Files/DupFiles1/DatabaseBills.accdb new file mode 100644 index 0000000..90679ba Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/DatabaseBills.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/DatabaseReceits.accdb b/DataAccessLayer/TestData/Files/DupFiles1/DatabaseReceits.accdb new file mode 100644 index 0000000..c0e3c70 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/DatabaseReceits.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Doc1.rtf b/DataAccessLayer/TestData/Files/DupFiles1/Doc1.rtf new file mode 100644 index 0000000..ca783c7 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/Doc1.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;} +{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid5513996}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot5513996 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 \hich\af1\dbch\af31505\loch\f1 Doc1.Rtf}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000002068 +d7b37398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Doc2.rtf b/DataAccessLayer/TestData/Files/DupFiles1/Doc2.rtf new file mode 100644 index 0000000..f6b7f34 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/Doc2.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid15009392}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot15009392 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15009392 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 \insrsid15009392 \hich\af31506\dbch\af31505\loch\f31506 Doc2.rtf}{\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 +\insrsid15009392\charrsid15009392 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f000000000000000000000000f00c +7fba7398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document1.docx b/DataAccessLayer/TestData/Files/DupFiles1/Document1.docx new file mode 100644 index 0000000..94dcb41 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document1.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document2.doc b/DataAccessLayer/TestData/Files/DupFiles1/Document2.doc new file mode 100644 index 0000000..97b5bf0 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document2.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document3.docx b/DataAccessLayer/TestData/Files/DupFiles1/Document3.docx new file mode 100644 index 0000000..07313b9 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document3.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document4.doc b/DataAccessLayer/TestData/Files/DupFiles1/Document4.doc new file mode 100644 index 0000000..b58cabf Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document4.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document5.docx b/DataAccessLayer/TestData/Files/DupFiles1/Document5.docx new file mode 100644 index 0000000..b8c0b62 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document5.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document6.docx b/DataAccessLayer/TestData/Files/DupFiles1/Document6.docx new file mode 100644 index 0000000..75e8bad Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document6.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Document7.docx b/DataAccessLayer/TestData/Files/DupFiles1/Document7.docx new file mode 100644 index 0000000..4f8c401 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Document7.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Doris likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles1/Doris likes apples.doc new file mode 100644 index 0000000..ececba8 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Doris likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Doris.xlsx b/DataAccessLayer/TestData/Files/DupFiles1/Doris.xlsx new file mode 100644 index 0000000..0672cc5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Doris.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Drawing1.vsd b/DataAccessLayer/TestData/Files/DupFiles1/Drawing1.vsd new file mode 100644 index 0000000..85e0a90 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Drawing1.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Drawing2.vsd b/DataAccessLayer/TestData/Files/DupFiles1/Drawing2.vsd new file mode 100644 index 0000000..e36bdbf Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Drawing2.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Map1.mmap b/DataAccessLayer/TestData/Files/DupFiles1/Map1.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Map1.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Map2.mmap b/DataAccessLayer/TestData/Files/DupFiles1/Map2.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Map2.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/MoreDefects.TXT b/DataAccessLayer/TestData/Files/DupFiles1/MoreDefects.TXT new file mode 100644 index 0000000..b9bbe1c --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/MoreDefects.TXT @@ -0,0 +1,5 @@ + + + +[ButtonHook] +- When W32Window get's a message and ::IsWindow(::GetParent(hWnd)) is false Close down everything!!! diff --git a/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap1.mm b/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap1.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap1.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap2.mm b/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap2.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/New Mindmap2.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles1/OogyKeepInMind.txt b/DataAccessLayer/TestData/Files/DupFiles1/OogyKeepInMind.txt new file mode 100644 index 0000000..1e3616f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/OogyKeepInMind.txt @@ -0,0 +1,27 @@ +[ShellExecuteLauncher.cs] +------------------------- +Right now ShellExecuteLauncher iterates thru all top level windows +until it finds the name of the file in the title bar. + +comments: +-to avoid collisions with duplicate file names (hold a map of + previous window handles), so if the file name is in the title and + it is not already mapped it's the new window. + +-maybe invoke bh or resolvers to do the work and skip title search + all together. + +Workspace launching (more testing to do with new resolver events) +~but one possibility could be: +------------------------- +launcher calls BH -> AboutToLaunchWorkspace(), button hook disables +all newly created buttons and listens for WM_CREATE and parentNotify_WM_CREATES... +... in order... that is our in order handle table. + +launcher calls BH -> LaunchDone(artifacts), we use the artifacts in order +in our table and launcher gets the list of handles. + +~this would work if launcher accurately launches in order and all windows +are created in order. ~launcher should wait till resolve event occurs? +~before launching next??? +-------------------------------------------- diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Presentation1.ppt b/DataAccessLayer/TestData/Files/DupFiles1/Presentation1.ppt new file mode 100644 index 0000000..390ef09 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Presentation1.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Presentation2.ppt b/DataAccessLayer/TestData/Files/DupFiles1/Presentation2.ppt new file mode 100644 index 0000000..a8c747b Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Presentation2.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Publication1.pub b/DataAccessLayer/TestData/Files/DupFiles1/Publication1.pub new file mode 100644 index 0000000..18d0764 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Publication1.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/Publication2.pub b/DataAccessLayer/TestData/Files/DupFiles1/Publication2.pub new file mode 100644 index 0000000..b75dfb8 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/Publication2.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/doris.docx b/DataAccessLayer/TestData/Files/DupFiles1/doris.docx new file mode 100644 index 0000000..26d3bd5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/doris.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/doris2.docx b/DataAccessLayer/TestData/Files/DupFiles1/doris2.docx new file mode 100644 index 0000000..124e9b5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles1/doris2.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles1/textfile1.txt b/DataAccessLayer/TestData/Files/DupFiles1/textfile1.txt new file mode 100644 index 0000000..de850da --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles1/textfile1.txt @@ -0,0 +1,11 @@ +WM_ENTERIDLE fuSource:MSGF_DIALOGBOX hwnd:001b11dc +WN_SETTEXT lpsz:000BEF18("SHELLY TO DO.txt - Notepad") + +[Open dialog sends the following things] +WM_COMMAND wNotifyCode:BN_CLICKED wID:IDOK hwndCtrl:004F092E +WM_NOTIFY idCtrl:1148 pnmh:000BEB30 +WM_NOTIFY idCtrl:1148 pnmh:000BEB6C + +[Tada!] +Use ::GetOpenFileName or ::GetSaveFileName passing pointer to a OPENFILENAME structure. + diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Albin likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles2/Albin likes apples.doc new file mode 100644 index 0000000..07ad7bc Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Albin likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book1.xls b/DataAccessLayer/TestData/Files/DupFiles2/Book1.xls new file mode 100644 index 0000000..13be6fb Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book1.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book1.xlsx b/DataAccessLayer/TestData/Files/DupFiles2/Book1.xlsx new file mode 100644 index 0000000..150de4a Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book1.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book2.xls b/DataAccessLayer/TestData/Files/DupFiles2/Book2.xls new file mode 100644 index 0000000..1adb97f Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book2.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book2.xlsx b/DataAccessLayer/TestData/Files/DupFiles2/Book2.xlsx new file mode 100644 index 0000000..715c15d Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book2.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book3.xls b/DataAccessLayer/TestData/Files/DupFiles2/Book3.xls new file mode 100644 index 0000000..7b14cfb Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book3.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Book4.xls b/DataAccessLayer/TestData/Files/DupFiles2/Book4.xls new file mode 100644 index 0000000..45a95f0 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Book4.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/DatabaseBills.accdb b/DataAccessLayer/TestData/Files/DupFiles2/DatabaseBills.accdb new file mode 100644 index 0000000..427bf49 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/DatabaseBills.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/DatabaseReceits.accdb b/DataAccessLayer/TestData/Files/DupFiles2/DatabaseReceits.accdb new file mode 100644 index 0000000..77b797a Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/DatabaseReceits.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Doc1.rtf b/DataAccessLayer/TestData/Files/DupFiles2/Doc1.rtf new file mode 100644 index 0000000..ca783c7 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/Doc1.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;} +{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid5513996}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot5513996 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 \hich\af1\dbch\af31505\loch\f1 Doc1.Rtf}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000002068 +d7b37398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Doc2.rtf b/DataAccessLayer/TestData/Files/DupFiles2/Doc2.rtf new file mode 100644 index 0000000..f6b7f34 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/Doc2.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid15009392}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot15009392 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15009392 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 \insrsid15009392 \hich\af31506\dbch\af31505\loch\f31506 Doc2.rtf}{\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 +\insrsid15009392\charrsid15009392 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f000000000000000000000000f00c +7fba7398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document1.docx b/DataAccessLayer/TestData/Files/DupFiles2/Document1.docx new file mode 100644 index 0000000..94dcb41 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document1.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document2.doc b/DataAccessLayer/TestData/Files/DupFiles2/Document2.doc new file mode 100644 index 0000000..97b5bf0 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document2.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document3.docx b/DataAccessLayer/TestData/Files/DupFiles2/Document3.docx new file mode 100644 index 0000000..07313b9 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document3.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document4.doc b/DataAccessLayer/TestData/Files/DupFiles2/Document4.doc new file mode 100644 index 0000000..b58cabf Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document4.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document5.docx b/DataAccessLayer/TestData/Files/DupFiles2/Document5.docx new file mode 100644 index 0000000..b8c0b62 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document5.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document6.docx b/DataAccessLayer/TestData/Files/DupFiles2/Document6.docx new file mode 100644 index 0000000..75e8bad Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document6.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Document7.docx b/DataAccessLayer/TestData/Files/DupFiles2/Document7.docx new file mode 100644 index 0000000..4f8c401 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Document7.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Doris likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles2/Doris likes apples.doc new file mode 100644 index 0000000..ececba8 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Doris likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Doris.xlsx b/DataAccessLayer/TestData/Files/DupFiles2/Doris.xlsx new file mode 100644 index 0000000..0672cc5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Doris.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Drawing1.vsd b/DataAccessLayer/TestData/Files/DupFiles2/Drawing1.vsd new file mode 100644 index 0000000..f1a9e28 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Drawing1.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Drawing2.vsd b/DataAccessLayer/TestData/Files/DupFiles2/Drawing2.vsd new file mode 100644 index 0000000..f1a9e28 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Drawing2.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Map1.mmap b/DataAccessLayer/TestData/Files/DupFiles2/Map1.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Map1.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Map2.mmap b/DataAccessLayer/TestData/Files/DupFiles2/Map2.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Map2.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/MoreDefects.TXT b/DataAccessLayer/TestData/Files/DupFiles2/MoreDefects.TXT new file mode 100644 index 0000000..b9bbe1c --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/MoreDefects.TXT @@ -0,0 +1,5 @@ + + + +[ButtonHook] +- When W32Window get's a message and ::IsWindow(::GetParent(hWnd)) is false Close down everything!!! diff --git a/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap1.mm b/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap1.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap1.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap2.mm b/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap2.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/New Mindmap2.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles2/OogyKeepInMind.txt b/DataAccessLayer/TestData/Files/DupFiles2/OogyKeepInMind.txt new file mode 100644 index 0000000..1e3616f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/OogyKeepInMind.txt @@ -0,0 +1,27 @@ +[ShellExecuteLauncher.cs] +------------------------- +Right now ShellExecuteLauncher iterates thru all top level windows +until it finds the name of the file in the title bar. + +comments: +-to avoid collisions with duplicate file names (hold a map of + previous window handles), so if the file name is in the title and + it is not already mapped it's the new window. + +-maybe invoke bh or resolvers to do the work and skip title search + all together. + +Workspace launching (more testing to do with new resolver events) +~but one possibility could be: +------------------------- +launcher calls BH -> AboutToLaunchWorkspace(), button hook disables +all newly created buttons and listens for WM_CREATE and parentNotify_WM_CREATES... +... in order... that is our in order handle table. + +launcher calls BH -> LaunchDone(artifacts), we use the artifacts in order +in our table and launcher gets the list of handles. + +~this would work if launcher accurately launches in order and all windows +are created in order. ~launcher should wait till resolve event occurs? +~before launching next??? +-------------------------------------------- diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Presentation1.ppt b/DataAccessLayer/TestData/Files/DupFiles2/Presentation1.ppt new file mode 100644 index 0000000..61d4880 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Presentation1.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Presentation2.ppt b/DataAccessLayer/TestData/Files/DupFiles2/Presentation2.ppt new file mode 100644 index 0000000..ce7f006 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Presentation2.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Publication1.pub b/DataAccessLayer/TestData/Files/DupFiles2/Publication1.pub new file mode 100644 index 0000000..215aa5b Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Publication1.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/Publication2.pub b/DataAccessLayer/TestData/Files/DupFiles2/Publication2.pub new file mode 100644 index 0000000..a0dda95 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/Publication2.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/doris.docx b/DataAccessLayer/TestData/Files/DupFiles2/doris.docx new file mode 100644 index 0000000..26d3bd5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/doris.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/doris2.docx b/DataAccessLayer/TestData/Files/DupFiles2/doris2.docx new file mode 100644 index 0000000..124e9b5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles2/doris2.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles2/textfile1.txt b/DataAccessLayer/TestData/Files/DupFiles2/textfile1.txt new file mode 100644 index 0000000..de850da --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles2/textfile1.txt @@ -0,0 +1,11 @@ +WM_ENTERIDLE fuSource:MSGF_DIALOGBOX hwnd:001b11dc +WN_SETTEXT lpsz:000BEF18("SHELLY TO DO.txt - Notepad") + +[Open dialog sends the following things] +WM_COMMAND wNotifyCode:BN_CLICKED wID:IDOK hwndCtrl:004F092E +WM_NOTIFY idCtrl:1148 pnmh:000BEB30 +WM_NOTIFY idCtrl:1148 pnmh:000BEB6C + +[Tada!] +Use ::GetOpenFileName or ::GetSaveFileName passing pointer to a OPENFILENAME structure. + diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Albin likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles3/Albin likes apples.doc new file mode 100644 index 0000000..07ad7bc Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Albin likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book1.xls b/DataAccessLayer/TestData/Files/DupFiles3/Book1.xls new file mode 100644 index 0000000..21c4c80 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book1.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book1.xlsx b/DataAccessLayer/TestData/Files/DupFiles3/Book1.xlsx new file mode 100644 index 0000000..150de4a Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book1.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book2.xls b/DataAccessLayer/TestData/Files/DupFiles3/Book2.xls new file mode 100644 index 0000000..7244f00 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book2.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book2.xlsx b/DataAccessLayer/TestData/Files/DupFiles3/Book2.xlsx new file mode 100644 index 0000000..715c15d Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book2.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book3.xls b/DataAccessLayer/TestData/Files/DupFiles3/Book3.xls new file mode 100644 index 0000000..e6cf8d9 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book3.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Book4.xls b/DataAccessLayer/TestData/Files/DupFiles3/Book4.xls new file mode 100644 index 0000000..45a95f0 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Book4.xls differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/DatabaseBills.accdb b/DataAccessLayer/TestData/Files/DupFiles3/DatabaseBills.accdb new file mode 100644 index 0000000..427bf49 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/DatabaseBills.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/DatabaseReceits.accdb b/DataAccessLayer/TestData/Files/DupFiles3/DatabaseReceits.accdb new file mode 100644 index 0000000..77b797a Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/DatabaseReceits.accdb differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Doc1.rtf b/DataAccessLayer/TestData/Files/DupFiles3/Doc1.rtf new file mode 100644 index 0000000..ca783c7 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/Doc1.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;} +{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid5513996}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot5513996 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 \hich\af1\dbch\af31505\loch\f1 Doc1.Rtf}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5513996 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000002068 +d7b37398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Doc2.rtf b/DataAccessLayer/TestData/Files/DupFiles3/Doc2.rtf new file mode 100644 index 0000000..f6b7f34 --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/Doc2.rtf @@ -0,0 +1,154 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid15009392}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator HPinvent} +{\creatim\yr2010\mo1\dy18\hr14\min23}{\revtim\yr2010\mo1\dy18\hr14\min23}{\version2}{\edmins0}{\nofpages1}{\nofwords1}{\nofchars8}{\nofcharsws8}{\vern32771}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot15009392 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15009392 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 \insrsid15009392 \hich\af31506\dbch\af31505\loch\f31506 Doc2.rtf}{\rtlch\fcs1 \af31507\afs20 \ltrch\fcs0 +\insrsid15009392\charrsid15009392 +\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 +72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 +2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b +44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 +065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 +00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 +84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc +52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 +bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 +656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c +070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 +29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 +312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 +a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 +98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c +94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 +7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 +9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 +e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 +193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 +17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 +8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 +6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a +668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 +bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e +16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b +5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 +8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 +c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 +0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b +7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb +9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 +088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf +8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 +ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 +28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 +345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 +b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 +254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 +68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 +51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 +720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 +a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 +000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 +002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 +656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 +00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 +00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f000000000000000000000000f00c +7fba7398ca01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document1.docx b/DataAccessLayer/TestData/Files/DupFiles3/Document1.docx new file mode 100644 index 0000000..94dcb41 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document1.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document2.doc b/DataAccessLayer/TestData/Files/DupFiles3/Document2.doc new file mode 100644 index 0000000..97b5bf0 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document2.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document3.docx b/DataAccessLayer/TestData/Files/DupFiles3/Document3.docx new file mode 100644 index 0000000..07313b9 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document3.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document4.doc b/DataAccessLayer/TestData/Files/DupFiles3/Document4.doc new file mode 100644 index 0000000..b58cabf Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document4.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document5.docx b/DataAccessLayer/TestData/Files/DupFiles3/Document5.docx new file mode 100644 index 0000000..b8c0b62 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document5.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document6.docx b/DataAccessLayer/TestData/Files/DupFiles3/Document6.docx new file mode 100644 index 0000000..75e8bad Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document6.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Document7.docx b/DataAccessLayer/TestData/Files/DupFiles3/Document7.docx new file mode 100644 index 0000000..4f8c401 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Document7.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Doris likes apples.doc b/DataAccessLayer/TestData/Files/DupFiles3/Doris likes apples.doc new file mode 100644 index 0000000..ececba8 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Doris likes apples.doc differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Doris.xlsx b/DataAccessLayer/TestData/Files/DupFiles3/Doris.xlsx new file mode 100644 index 0000000..0672cc5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Doris.xlsx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Drawing1.vsd b/DataAccessLayer/TestData/Files/DupFiles3/Drawing1.vsd new file mode 100644 index 0000000..f1a9e28 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Drawing1.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Drawing2.vsd b/DataAccessLayer/TestData/Files/DupFiles3/Drawing2.vsd new file mode 100644 index 0000000..f1a9e28 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Drawing2.vsd differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Map1.mmap b/DataAccessLayer/TestData/Files/DupFiles3/Map1.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Map1.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Map2.mmap b/DataAccessLayer/TestData/Files/DupFiles3/Map2.mmap new file mode 100644 index 0000000..14fb76e Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Map2.mmap differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/MoreDefects.TXT b/DataAccessLayer/TestData/Files/DupFiles3/MoreDefects.TXT new file mode 100644 index 0000000..b9bbe1c --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/MoreDefects.TXT @@ -0,0 +1,5 @@ + + + +[ButtonHook] +- When W32Window get's a message and ::IsWindow(::GetParent(hWnd)) is false Close down everything!!! diff --git a/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap1.mm b/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap1.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap1.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap2.mm b/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap2.mm new file mode 100644 index 0000000..e88a40f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/New Mindmap2.mm @@ -0,0 +1,4 @@ + + + + diff --git a/DataAccessLayer/TestData/Files/DupFiles3/OogyKeepInMind.txt b/DataAccessLayer/TestData/Files/DupFiles3/OogyKeepInMind.txt new file mode 100644 index 0000000..1e3616f --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/OogyKeepInMind.txt @@ -0,0 +1,27 @@ +[ShellExecuteLauncher.cs] +------------------------- +Right now ShellExecuteLauncher iterates thru all top level windows +until it finds the name of the file in the title bar. + +comments: +-to avoid collisions with duplicate file names (hold a map of + previous window handles), so if the file name is in the title and + it is not already mapped it's the new window. + +-maybe invoke bh or resolvers to do the work and skip title search + all together. + +Workspace launching (more testing to do with new resolver events) +~but one possibility could be: +------------------------- +launcher calls BH -> AboutToLaunchWorkspace(), button hook disables +all newly created buttons and listens for WM_CREATE and parentNotify_WM_CREATES... +... in order... that is our in order handle table. + +launcher calls BH -> LaunchDone(artifacts), we use the artifacts in order +in our table and launcher gets the list of handles. + +~this would work if launcher accurately launches in order and all windows +are created in order. ~launcher should wait till resolve event occurs? +~before launching next??? +-------------------------------------------- diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Presentation1.ppt b/DataAccessLayer/TestData/Files/DupFiles3/Presentation1.ppt new file mode 100644 index 0000000..61d4880 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Presentation1.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Presentation2.ppt b/DataAccessLayer/TestData/Files/DupFiles3/Presentation2.ppt new file mode 100644 index 0000000..ce7f006 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Presentation2.ppt differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Publication1.pub b/DataAccessLayer/TestData/Files/DupFiles3/Publication1.pub new file mode 100644 index 0000000..215aa5b Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Publication1.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/Publication2.pub b/DataAccessLayer/TestData/Files/DupFiles3/Publication2.pub new file mode 100644 index 0000000..a0dda95 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/Publication2.pub differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/doris.docx b/DataAccessLayer/TestData/Files/DupFiles3/doris.docx new file mode 100644 index 0000000..26d3bd5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/doris.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/doris2.docx b/DataAccessLayer/TestData/Files/DupFiles3/doris2.docx new file mode 100644 index 0000000..124e9b5 Binary files /dev/null and b/DataAccessLayer/TestData/Files/DupFiles3/doris2.docx differ diff --git a/DataAccessLayer/TestData/Files/DupFiles3/textfile1.txt b/DataAccessLayer/TestData/Files/DupFiles3/textfile1.txt new file mode 100644 index 0000000..de850da --- /dev/null +++ b/DataAccessLayer/TestData/Files/DupFiles3/textfile1.txt @@ -0,0 +1,11 @@ +WM_ENTERIDLE fuSource:MSGF_DIALOGBOX hwnd:001b11dc +WN_SETTEXT lpsz:000BEF18("SHELLY TO DO.txt - Notepad") + +[Open dialog sends the following things] +WM_COMMAND wNotifyCode:BN_CLICKED wID:IDOK hwndCtrl:004F092E +WM_NOTIFY idCtrl:1148 pnmh:000BEB30 +WM_NOTIFY idCtrl:1148 pnmh:000BEB6C + +[Tada!] +Use ::GetOpenFileName or ::GetSaveFileName passing pointer to a OPENFILENAME structure. + diff --git a/DataAccessLayer/TestData/Files/Snapshots/c9f487bd-7cef-4f45-8238-08a4be0a3ba3.png b/DataAccessLayer/TestData/Files/Snapshots/c9f487bd-7cef-4f45-8238-08a4be0a3ba3.png new file mode 100644 index 0000000..a8c917e Binary files /dev/null and b/DataAccessLayer/TestData/Files/Snapshots/c9f487bd-7cef-4f45-8238-08a4be0a3ba3.png differ diff --git a/DataAccessLayer/TestData/TestData.cs b/DataAccessLayer/TestData/TestData.cs new file mode 100644 index 0000000..ae7ea99 --- /dev/null +++ b/DataAccessLayer/TestData/TestData.cs @@ -0,0 +1,348 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using DataAccessLayer.TestData; +using System.Threading; +using System.IO; +using System.Diagnostics; + +namespace DataAccessLayer.TestData +{ + public static class TestData + { + // Project / Directory Constants + private const string PROJECT_NAME = "DataAccessLayer"; + private const string TEST_DATADIR_NAME = "TestData"; + private const string TEST_DATADIRFILES_NAME = "Files"; + private const string TEST_DATADIREFILESSNAPSHOT_NAME = "Snapshots"; + private const string TEST_DATADIRFILESDUPFILESDIR = "DupFiles"; + + // Internally calculated locations + private static string _TestDataDirFilesLocation = ""; + private static string _TestDataDirFilesSnapshotLocation = ""; + + /// + /// Static Constructor is responsible for setting up the locationpaths + /// + static TestData() + { + _TestDataDirFilesLocation = GetTestDataFilesDirectoryFromRunningAssembly(Assembly.GetExecutingAssembly().Location); + if (!String.IsNullOrEmpty(_TestDataDirFilesLocation)) + _TestDataDirFilesSnapshotLocation = _TestDataDirFilesLocation + "\\" + TEST_DATADIREFILESSNAPSHOT_NAME; + + // Now Load our File Name Map + LoadTestDataFilesIntoOurList(); + } + + /// + /// Private Data struct useful for our TestData Files + /// + private class TestDataFile + { + public string Name { get; set; } + public string File { get; set; } + public string Type { get; set; } + public TestDataFile(string Name, string File, string Type) + { + this.Name = Name; + this.File = File; + this.Type = Type; + } + } + + // Holds all our TestData Files + private static List _testDataFiles = new List(); + + // Get a new Random Number + private static int RandomNumber(int min, int max) + { + Random random = new Random(); + return random.Next(min, max); + } + + /// + /// Loads our TestFiles Into our Private Map + /// + private static void LoadTestDataFilesIntoOurList() + { + _testDataFiles.Add(new TestDataFile("Albin likes apples", "Albin likes apples.doc", "doc")); + _testDataFiles.Add(new TestDataFile("Book1", "Book1.xls", "xls")); + _testDataFiles.Add(new TestDataFile("Book1", "Book1.xlsx", "xlsx")); + _testDataFiles.Add(new TestDataFile("Book2", "Book2.xls", "xls")); + _testDataFiles.Add(new TestDataFile("Book2", "Book2.xlsx", "xlsx")); + _testDataFiles.Add(new TestDataFile("Book3", "Book3.xls", "xls")); + _testDataFiles.Add(new TestDataFile("Book3", "Book4.xls", "xls")); + _testDataFiles.Add(new TestDataFile("DatabaseBills", "DatabaseBills.accdb", "accdb")); + _testDataFiles.Add(new TestDataFile("DatabaseReceits", "DatabaseReceits.accdb", "accdb")); + _testDataFiles.Add(new TestDataFile("Doc1", "Doc1.rtf", "rtf")); + _testDataFiles.Add(new TestDataFile("Doc2", "Doc2.rtf", "rtf")); + + //// Artifacts used in ThreadProc13 *Begin* + _testDataFiles.Add(new TestDataFile("Document1", "Document1.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Document2", "Document2.doc", "doc")); + _testDataFiles.Add(new TestDataFile("Document3", "Document3.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Document4", "Document4.doc", "doc")); + _testDataFiles.Add(new TestDataFile("Document5", "Document5.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Document6", "Document6.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Document7", "Document7.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Doris liks apples", "Doris likes apples.doc", "doc")); + _testDataFiles.Add(new TestDataFile("Doris", "Doris.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Doris", "Doris.xlsx", "xlsx")); + _testDataFiles.Add(new TestDataFile("Doris2", "Doris2.docx", "docx")); + _testDataFiles.Add(new TestDataFile("Drawing1", "Drawing1.vsd", "vsd")); + _testDataFiles.Add(new TestDataFile("Drawing2", "Drawing2.vsd", "vsd")); + _testDataFiles.Add(new TestDataFile("Map1", "Map1.mmap", "mmap")); + _testDataFiles.Add(new TestDataFile("Map2", "Map2.mmap", "mmap")); + //// Artifacts used in ThreadProc13 *End* + + _testDataFiles.Add(new TestDataFile("MoreDefects", "MoreDefects.txt", "txt")); + _testDataFiles.Add(new TestDataFile("New Mindmap1", "New Mindmap1.mm", "mm")); + _testDataFiles.Add(new TestDataFile("New Mindmap2", "New Mindmap2.mm", "mm")); + _testDataFiles.Add(new TestDataFile("OogyKeepInMind", "OogyKeepInMind.txt", "txt")); + _testDataFiles.Add(new TestDataFile("Presentation1", "Presentation1.ppt", "ppt")); + _testDataFiles.Add(new TestDataFile("Presentation2", "Presentation2.ppt", "ppt")); + _testDataFiles.Add(new TestDataFile("Publication1", "Publication1.pub", "pub")); + _testDataFiles.Add(new TestDataFile("Publication2", "Publication2.pub", "pub")); + _testDataFiles.Add(new TestDataFile("textfile1", "textfile1.txt", "txt")); + + // Sort the List by File Type + _testDataFiles.Sort(delegate(TestDataFile t1, TestDataFile t2) { return t1.Type.CompareTo(t2.Type); }); + } + + /// + /// Fills Default Database with Test Data + /// + public static void FillDBWithTestData() + { + if (!String.IsNullOrEmpty(_TestDataDirFilesLocation) && !String.IsNullOrEmpty(_TestDataDirFilesSnapshotLocation)) + { + + #region File Type Workspaces + //// + // First Let's Create a workspace for each file Type + //// + string FileType = String.Empty; + string strWorkspaceName = String.Empty; + foreach (TestDataFile dataFile in _testDataFiles) + { + bool bFileTypeIsSet = false; + if (String.IsNullOrEmpty(FileType)) + { + FileType = dataFile.Type; + bFileTypeIsSet = true; + } + else if (FileType != dataFile.Type) + { + FileType = dataFile.Type; + bFileTypeIsSet = true; + } + + // Create New FileType Based Workspace + if (bFileTypeIsSet) + { + strWorkspaceName = "FileType Workspace for ." + FileType; + Debug.Assert(Data.Workspace.InsertWorkspaceName(strWorkspaceName)); + } + + // Add the Artifact to the corresponding Workspace + Debug.Assert(AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, strWorkspaceName, 1)); + } + #endregion + + #region Simple Word and Excel + //// + // Let's create a Simple Word and Excel Workspace + //// + Debug.Assert(Data.Workspace.InsertWorkspaceName("Office Simple doc & xls")); + foreach (TestDataFile dataFile in _testDataFiles) + { + if (dataFile.Type == "doc" || + dataFile.Type == "xls") + { + // Add the Artifact to the corresponding Workspace + Debug.Assert(AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "Office Simple doc & xls", 1)); + } + } + #endregion + + #region Advanced Word and Excel + //// + // Let's create a Advanced Word and Excel Workspace + //// + Debug.Assert(Data.Workspace.InsertWorkspaceName("Office Advanced docx & xlsx")); + foreach (TestDataFile dataFile in _testDataFiles) + { + if (dataFile.Type == "docx" || + dataFile.Type == "xlsx") + { + // Add the Artifact to the corresponding Workspace + Debug.Assert(AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "Office Advanced docx & xlsx", 1)); + } + } + #endregion + + #region PowerPoint and Text Files + //// + // Let's create a Ppt and Txt files workspace for now + //// + Debug.Assert(Data.Workspace.InsertWorkspaceName("PowerPoint and Text Files")); + foreach (TestDataFile dataFile in _testDataFiles) + { + if (dataFile.Type == "ppt" || + dataFile.Type == "txt") + { + // Add the Artifact to the corresponding Workspace + Debug.Assert(AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "PowerPoint and Text Files", 1)); + } + } + #endregion + + #region ShuffleWorkspace1 - 7 Items + Debug.Assert(Data.Workspace.InsertWorkspaceName("ShuffleWorkspace1 - 7 Items")); + for (int i = 0; i < 7; ++i) + { + TestDataFile dataFile = _testDataFiles[RandomNumber(0, _testDataFiles.Count)]; + AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "ShuffleWorkspace1 - 7 Items", 1); + } + #endregion + + #region ShuffleWorkspace2 - 6 Items + Debug.Assert(Data.Workspace.InsertWorkspaceName("ShuffleWorkspace2 - 6 Items")); + for (int i = 0; i < 6; ++i) + { + TestDataFile dataFile = _testDataFiles[RandomNumber(0, _testDataFiles.Count)]; + AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "ShuffleWorkspace2 - 6 Items", 1); + } + #endregion + + #region ShuffleWorkspace3 - 5 Items + Debug.Assert(Data.Workspace.InsertWorkspaceName("ShuffleWorkspace3 - 5 Items")); + for (int i = 0; i < 5; ++i) + { + TestDataFile dataFile = _testDataFiles[RandomNumber(0, _testDataFiles.Count)]; + AddTestArtifactToWorkspace(dataFile.Name, dataFile.File, "ShuffleWorkspace3 - 5 Items", 1); + } + #endregion + + #region DuplicateWorkspace1 + int nNumberOfArtifacts1 = RandomNumber(3, 10); + string strDupWkspace1 = "DuplicateWorkspace1 - " + nNumberOfArtifacts1.ToString() + " Items"; + Debug.Assert(Data.Workspace.InsertWorkspaceName(strDupWkspace1)); + for (int i = 0; i < nNumberOfArtifacts1; ++i ) + { + int nDuplicates = RandomNumber(1, 3); + int nArtifact = RandomNumber(0, _testDataFiles.Count); + + // Add Duplicates + for (int j = 1; j <= nDuplicates; ++j) + AddTestArtifactToWorkspace(_testDataFiles[nArtifact].Name, _testDataFiles[nArtifact].File, strDupWkspace1 , j); + } + #endregion + + #region DuplicateWorkspace2 + int nNumberOfArtifacts2 = RandomNumber(3, 10); + string strDupWkspace2 = "DuplicateWorkspace2 - " + nNumberOfArtifacts2.ToString() + " Items"; + Debug.Assert(Data.Workspace.InsertWorkspaceName(strDupWkspace2)); + for (int i = 0; i < nNumberOfArtifacts2; ++i) + { + int nDuplicates = RandomNumber(1, 3); + int nArtifact = RandomNumber(0, _testDataFiles.Count); + + // Add Duplicates + for (int j = 1; j <= nDuplicates; ++j) + AddTestArtifactToWorkspace(_testDataFiles[nArtifact].Name, _testDataFiles[nArtifact].File, strDupWkspace2, j); + } + #endregion + + #region DuplicateWorkspace3 + int nNumberOfArtifacts3 = RandomNumber(3, 10); + string strDupWkspace3 = "DuplicateWorkspace3 - " + nNumberOfArtifacts3.ToString() + " Items"; + Debug.Assert(Data.Workspace.InsertWorkspaceName(strDupWkspace3)); + for (int i = 0; i < nNumberOfArtifacts3; ++i) + { + int nDuplicates = RandomNumber(1, 3); + int nArtifact = RandomNumber(0, _testDataFiles.Count); + + // Add Duplicates + for (int j = 1; j <= nDuplicates; ++j) + AddTestArtifactToWorkspace(_testDataFiles[nArtifact].Name, _testDataFiles[nArtifact].File, strDupWkspace3, j); + } + #endregion + } + } + + /// + /// Quick Helper Function to add Test Artifacts to a Workspace + /// + /// Name of the artifact you would like to give + /// name of the file such as File1.jpg + /// name of workspace to add to + /// pass in a number from 1 - 3 (i have 3 dup directories) + /// true, if successfully added, false otherwise + public static bool AddTestArtifactToWorkspace(string ArtifactName, string FileName, string WorkspaceName, int DupFileDirIndex) + { + if (!String.IsNullOrEmpty(_TestDataDirFilesLocation) && !String.IsNullOrEmpty(_TestDataDirFilesSnapshotLocation)) + { + ArtifactItem artifactItem = new ArtifactItem() + { + Name = ArtifactName, + Location = _TestDataDirFilesLocation + "\\" + TEST_DATADIRFILESDUPFILESDIR + DupFileDirIndex.ToString() + "\\" + FileName, + SnapshotFile = _TestDataDirFilesSnapshotLocation + "\\" + "c9f487bd-7cef-4f45-8238-08a4be0a3ba3.png", + Note = "", + WindowLeft = 100, + WindowTop = 100, + WindowHeight = 400, + WindowWidth = 400, + }; + + artifactItem.SetAsFileType(); + return Data.Artifacts.AddArtifactToWorkspace(WorkspaceName, artifactItem); + } + return false; + } + + /// + /// Iterate and find the TestData Directory in the executing path + /// + /// location of currently executing assembly + /// valid path string to test data or "" if not found + private static string GetTestDataFilesDirectoryFromRunningAssembly(string AssemblyLocation) + { + DirectoryInfo directory = new DirectoryInfo(Path.GetDirectoryName(AssemblyLocation)); + + //// + // Iterate the executing Assembly Directory upward to find the testData or Project Directory + //// + bool bFindTestData = false; + while (!bFindTestData && (directory != null) && directory.Exists) + { + + // First Check to see if this Directory has the ProjectName as a SubDir + DirectoryInfo[] dirProjectNameDirs = directory.GetDirectories(PROJECT_NAME, SearchOption.TopDirectoryOnly); + + if(dirProjectNameDirs.Length == 1) + { + // Check if there is a TestData Dir Underneath (return if there is) + DirectoryInfo[] dirTestDataDirs = dirProjectNameDirs[0].GetDirectories(TEST_DATADIR_NAME, SearchOption.TopDirectoryOnly); + + if(dirTestDataDirs.Length == 1) + { + // Now Check for the Files Directory + DirectoryInfo[] dirTestDataFilesDirs = dirTestDataDirs[0].GetDirectories(TEST_DATADIRFILES_NAME, SearchOption.TopDirectoryOnly); + + if (dirTestDataFilesDirs.Length == 1) + return dirTestDataFilesDirs[0].FullName; + } + } + + // Keep going up the chain + directory = directory.Parent; + } + return String.Empty; + } + } +} diff --git a/DataAccessLayer/Tests/StressTest.cs b/DataAccessLayer/Tests/StressTest.cs new file mode 100644 index 0000000..f653d05 --- /dev/null +++ b/DataAccessLayer/Tests/StressTest.cs @@ -0,0 +1,572 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using DataAccessLayer.TestData; +using System.Threading; +using System.IO; + +namespace DataAccessLayer.Tests +{ + /// + /// Use this class to do a ThreadStressTest on the DB + /// Launch this class via CommandLine app and Call RunStressTest() + /// + internal static class StressTest + { + const int THREAD_SLEEP_EACH_ITERATION = 5; + + /// + /// Thread1 - Test ArtifactGroup Reading + /// + static private void ThreadProc1() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread1 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread1 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread2 - Test ArtifactGroup Reading + /// + static private void ThreadProc2() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread2 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread2 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread3 - Test ArtifactGroup Reading + /// + static private void ThreadProc3() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread3 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread3 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread4 - Test ArtifactGroup Reading + /// + static private void ThreadProc4() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread4 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread4 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread5 - Test ArtifactGroup Reading + /// + static private void ThreadProc5() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread5 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread5 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread3 - Test ArtifactGroup Reading + /// + static private void ThreadProc6() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread6 - Error : Workspacenames is wrong length"); + continue; + } + + foreach (string workspacename in workspacenames) + { + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread6 - Error : ArtifactGroup is Empty"); + } + } + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread7 - Test Artifact part of a Workspace + /// + static private void ThreadProc7() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread7 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[0], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread7 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[0], artifactItem)) + Console.WriteLine("Thread7 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread8 - Test Artifact part of a Workspace + /// + static private void ThreadProc8() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread8 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[1], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread8 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[1], artifactItem)) + Console.WriteLine("Thread8 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread9 - Test Artifact part of a Workspace + /// + static private void ThreadProc9() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread9 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[2], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread9 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[2], artifactItem)) + Console.WriteLine("Thread9 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread10 - Test Artifact part of a Workspace + /// + static private void ThreadProc10() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread10 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[0], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread10 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[0], artifactItem)) + Console.WriteLine("Thread10 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread11 - Test Artifact part of a Workspace + /// + static private void ThreadProc11() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread11 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[1], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread11 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[1], artifactItem)) + Console.WriteLine("Thread11 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread12 - Test Artifact part of a Workspace + /// + static private void ThreadProc12() + { + while (true) + { + string[] workspacenames = Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending); + if (workspacenames.Length <= 1) + { + Console.WriteLine("Thread12 - Error : Workspacenames is wrong length"); + continue; + } + + ArtifactItem[] artifactItems = Data.Artifacts.GetAllArtifactsForWorkspace(workspacenames[2], SortOrderForArtifacts.Ascending); + if (DataTypeValidation.IsEmptyArtifactItemGroup(artifactItems)) + { + Console.WriteLine("Thread12 - Error : ArtifactGroup is Empty"); + } + else + { + foreach (ArtifactItem artifactItem in artifactItems) + { + if (!Data.Artifacts.IsArtifactPartOfWorkspace(workspacenames[2], artifactItem)) + Console.WriteLine("Thread12 - Error: Artifact / Workspace Validation Error"); + } + } + + Thread.Sleep(THREAD_SLEEP_EACH_ITERATION); + } + } + + /// + /// Thread13 - Create a Write Artifact Thread! (Let's see what happens) + /// + static private void ThreadProc13() + { + //while (true) + //{ + // bool bSuccess = false; + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document1", "Document1.docx", "ProjectNotes"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document2", "Document2.doc", "ProjectNotes"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document3", "Document3.docx", "Office"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document4", "Document4.doc", "Presentations"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document5", "Document5.docx", "Presentations"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document6", "Document6.docx", "Presentations"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Document7", "Document7.docx", "Office"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Doris", "Doris.xlsx", "ProjectNotes"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Doris2", "Doris2.docx", "ProjectNotes"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Doris liks apples", "Doris likes apples.doc", "Office"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Drawing1", "Drawing1.vsd", "MyMindMaps"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Drawing2", "Drawing2.vsd", "MyMindMaps"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Map1", "Map1.mmap", "MyMindMaps"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + + // bSuccess = TestData.TestData.AddTestArtifactToWorkspace("Map2", "Map2.mmap", "MyMindMaps"); + // if (!bSuccess) + // Console.WriteLine("Thread13 - Error: Adding Artifact Failed!"); + + // Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + //} + } + + /// + /// Thread14 - Create another Write Artifact Thread! (Let's see what happens) + /// + static private void ThreadProc14() + { + while (true) + { + foreach (string workspacename in Data.Workspace.GetAllWorkspaceNames(SortOrderForWorkspaces.Ascending)) + { + ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(workspacename, SortOrderForArtifacts.Ascending); + + if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts)) + { + foreach (ArtifactItem artifact in artifacts) + { + artifact.WindowHeight = 678; + if (!Data.Artifacts.ModifyExistingArtifactProperties(artifact, workspacename)) + { + Console.WriteLine("Thread14 - Error: ModifyExistingArtifactProperties Failed"); + } + } + } + else + { + Console.WriteLine("Thread14 - Error: artifactsgroup is empty"); + } + } + + Thread.Sleep((20 * THREAD_SLEEP_EACH_ITERATION)); + } + } + + /// + /// Entry Point for running all the thread tests + /// + static public void RunStressTest() + { + Console.WriteLine("TestDataAccessLayer"); + Thread thread1 = new Thread(new ThreadStart(StressTest.ThreadProc1)); + Thread thread2 = new Thread(new ThreadStart(StressTest.ThreadProc2)); + Thread thread3 = new Thread(new ThreadStart(StressTest.ThreadProc3)); + Thread thread4 = new Thread(new ThreadStart(StressTest.ThreadProc4)); + Thread thread5 = new Thread(new ThreadStart(StressTest.ThreadProc5)); + Thread thread6 = new Thread(new ThreadStart(StressTest.ThreadProc6)); + Thread thread7 = new Thread(new ThreadStart(StressTest.ThreadProc7)); + Thread thread8 = new Thread(new ThreadStart(StressTest.ThreadProc8)); + Thread thread9 = new Thread(new ThreadStart(StressTest.ThreadProc9)); + Thread thread10 = new Thread(new ThreadStart(StressTest.ThreadProc10)); + Thread thread11 = new Thread(new ThreadStart(StressTest.ThreadProc11)); + Thread thread12 = new Thread(new ThreadStart(StressTest.ThreadProc12)); + Thread thread13 = new Thread(new ThreadStart(StressTest.ThreadProc13)); + Thread thread14 = new Thread(new ThreadStart(StressTest.ThreadProc14)); + Console.WriteLine("Threads Created"); + + //// + // Start All the Threads + //// + thread1.Start(); + thread2.Start(); + thread3.Start(); + thread4.Start(); + thread5.Start(); + thread6.Start(); + thread7.Start(); + thread8.Start(); + thread9.Start(); + thread10.Start(); + thread11.Start(); + thread12.Start(); + thread13.Start(); + thread14.Start(); + + Console.WriteLine("Threads Started...."); + + Console.WriteLine("To Quit Press the 'Q' Key and then Enter"); + while (true) + { + string str = Console.ReadLine(); + if (str == "Q" || str == "q") + { + break; + } + System.Threading.Thread.Sleep(100); + } + + Console.WriteLine("Stopping Threads...."); + thread1.Abort(); + thread2.Abort(); + thread3.Abort(); + thread4.Abort(); + thread5.Abort(); + thread6.Abort(); + thread7.Abort(); + thread8.Abort(); + thread9.Abort(); + thread10.Abort(); + thread11.Abort(); + thread12.Abort(); + thread13.Abort(); + thread14.Abort(); + } + } +} diff --git a/DataAccessLayer/app.config b/DataAccessLayer/app.config new file mode 100644 index 0000000..a515812 --- /dev/null +++ b/DataAccessLayer/app.config @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/DataAccessLayer/dArtifacts.cs b/DataAccessLayer/dArtifacts.cs new file mode 100644 index 0000000..3c5f27d --- /dev/null +++ b/DataAccessLayer/dArtifacts.cs @@ -0,0 +1,874 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Data.SqlServerCe; +using System.IO; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.DataAccessLayer +{ + public class dArtifacts + { + /// + /// Checks to see if this artifact is already in the system. The Location is the UniqueID + /// so no other artifact may exist that has the exact same location + /// + /// Artifact To Check (Location Needed Only) + /// true if found, false otherwise + public bool DoesArtifactExistInSystem(ArtifactItem artifactItem) + { + // Check Artifact Integrity + if ((artifactItem == null) || + !artifactItem.IsLocationValid) + return false; + + object obj = null; + lock (this) + { + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + } + return (obj != null); + } + + /// + /// Searches all Artifact's Names & Notes for the specified SearchQuery using SQL's Like stmt + /// + /// string to use in 'Like' (Must be less than 75 Characters) + /// Specify Sort Order + /// returns ArtifactItem[] of all found artifacts + public ArtifactItem[] SearchArtifactsInTheSystem(string SearchQuery, SortOrderForArtifacts SortOrder) + { + if (!String.IsNullOrEmpty(SearchQuery) && (SearchQuery.Length <= 75)) + { + lock (this) + { + DataSet dataset = SearchArtifactsInTheSystemIntoDataSet(SearchQuery, SortOrder); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + int nRows = dataset.Tables[0].Rows.Count; + ArtifactItem[] resultArtifacts = new ArtifactItem[nRows]; + + for (int i = 0; i < nRows; ++i) + { + DataRow datarow = dataset.Tables[0].Rows[i]; + resultArtifacts[i] = new ArtifactItem(); + + // Add Artifact Fields + resultArtifacts[i].Name = datarow["Name"].ToString(); + resultArtifacts[i].SetType(datarow["Type"].ToString()); + resultArtifacts[i].Location = datarow["Location"].ToString(); + resultArtifacts[i].Note = datarow["Note"].ToString(); + resultArtifacts[i].SnapshotFile = datarow["SnapShotFile"].ToString(); + + if (!String.IsNullOrEmpty(datarow["LastAccessed"].ToString())) + resultArtifacts[i].SetLastAccessed(DateTime.Parse(datarow["LastAccessed"].ToString())); + + if (!String.IsNullOrEmpty(datarow["AccessCounter"].ToString())) + resultArtifacts[i].AccessCounter = int.Parse(datarow["AccessCounter"].ToString()); + } + return resultArtifacts; + } + } + } + + // return Blank Item + return DataTypeHelpers.EmptyArtifactItemGroup(); + } + + /// + /// Searches all Artifact's Names & Notes for the specified SearchQuery using SQL's Like stmt + /// + /// string to use in 'Like' (Must be less than 75 Characters) + /// Specify Sort Order + /// returns DataSet of all found artifacts + public DataSet SearchArtifactsInTheSystemIntoDataSet(string SearchQuery, SortOrderForArtifacts SortOrder) + { + if (!String.IsNullOrEmpty(SearchQuery) && (SearchQuery.Length <= 75)) + { + lock (this) + { + string sql = "SELECT [Name],[Type],[Location],[Note],[SnapShotFile],[LastAccessed],[AccessCounter] FROM Artifacts"; + sql = sql + String.Format(" WHERE [Name] LIKE '%{0}%' OR [Note] LIKE '%{0}%' OR [Location] LIKE '%{0}%'", SearchQuery); + sql = SortOrderSQLHelpers.SortOrderForArtifactsHelper(sql, SortOrder); + DataSet dataset = DB.RunSQLTextFillDataSet(sql); + return dataset; + } + } + return new DataSet(); // empty dataset + } + + /// + /// Returns an ArtifactItem[] of all Artifacts in the System (WorkspaceLinkProperties won't be filled in) + /// + /// Specify Sort Order + /// returns ArtifactItem[] of all artifacts + public ArtifactItem[] GetAllArtifactsInTheSystem(SortOrderForArtifacts SortOrder) + { + lock (this) + { + DataSet dataset = GetAllArtifactsInTheSystemIntoDataSet(SortOrder); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + int nRows = dataset.Tables[0].Rows.Count; + ArtifactItem[] resultArtifacts = new ArtifactItem[nRows]; + + for (int i = 0; i < nRows; ++i) + { + DataRow datarow = dataset.Tables[0].Rows[i]; + resultArtifacts[i] = new ArtifactItem(); + + // Add Artifact Fields + resultArtifacts[i].Name = datarow["Name"].ToString(); + resultArtifacts[i].Type = (ArtifactTypes) Enum.Parse(typeof(ArtifactTypes), datarow["Type"].ToString(), true); + resultArtifacts[i].Location = datarow["Location"].ToString(); + resultArtifacts[i].Note = datarow["Note"].ToString(); + resultArtifacts[i].SnapshotFile = datarow["SnapShotFile"].ToString(); + + if (!String.IsNullOrEmpty(datarow["LastAccessed"].ToString())) + resultArtifacts[i].SetLastAccessed(DateTime.Parse(datarow["LastAccessed"].ToString())); + + if (!String.IsNullOrEmpty(datarow["AccessCounter"].ToString())) + resultArtifacts[i].AccessCounter = int.Parse(datarow["AccessCounter"].ToString()); + } + return resultArtifacts; + } + } + + // return Blank Item + return DataTypeHelpers.EmptyArtifactItemGroup(); + } + + /// + /// Returns a DataSet of All Artifacts in the System (WorkspaceLinkProperties won't be filled in) + /// + /// Specify Sort Order + /// returns DataSet of all artifacts + public DataSet GetAllArtifactsInTheSystemIntoDataSet(SortOrderForArtifacts SortOrder) + { + lock (this) + { + string sql = "SELECT [Name],[Type],[Location],[Note],[SnapShotFile],[LastAccessed],[AccessCounter] FROM Artifacts"; + sql = SortOrderSQLHelpers.SortOrderForArtifactsHelper(sql, SortOrder); + DataSet dataset = DB.RunSQLTextFillDataSet(sql); + return dataset; + } + } + + /// + /// Increments the access counter and sets LastAccessed for the + /// specified artifact. Call this whenever you have launched an Artifact. + /// + /// Artifact To Check (Location Needed Only) + /// true if successful set the internal counters, false otherwise + public bool ArtifactWasLaunched(ArtifactItem artifactItem) + { + // Check Artifact Validity + if ((artifactItem == null) || + !artifactItem.IsLocationValid) + return false; + + lock (this) + { + // existence check + if (!DoesArtifactExistInSystem(artifactItem)) + return false; + + // First Step - is to get the AccessCounter already in the db + string sql = "SELECT [AccessCounter] FROM Artifacts WHERE [Location]=@location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + + int accesscount = 1; + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + if (obj != null) + { + accesscount = int.Parse(obj.ToString()); + accesscount = accesscount + 1; // increment by 1 + } + + // Second Step - is to set the access counter and today's date for the artifact + string sql2 = "UPDATE Artifacts SET [LastAccessed]=@lastaccessed,[AccessCounter]=@accesscounter WHERE [Location]=@location"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@lastaccessed", DateTime.Now), + new SqlCeParameter("@accesscounter", accesscount), + new SqlCeParameter("@location", artifactItem.Location), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + return (nResult == 1); + } + } + + /// + /// Check to see if the artifact is part of the workspace + /// + /// WorskpaceName to check the Artifact against + /// Artifact To Check (Location Needed Only) + /// true, if part of the specified workspace, false otherwise + public bool IsArtifactPartOfWorkspace(string WorkspaceName, ArtifactItem artifactItem) + { + // Check Artifact & Workspace Validity + if ((artifactItem == null) || + !artifactItem.IsLocationValid || + !DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + object obj = null; + lock (this) + { + // Check to make sure that this is a valid WorkspaceName + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return false; + + // First Step - Get the UID of the Artifact to look up in the Links table + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + + if (obj != null) + { + int uid = int.Parse(obj.ToString()); + + // Second Step - Lookup if there is any item in the Links table that matches the uid and workspace name + string sql2 = "SELECT [UID] FROM WorkspaceLinks WHERE [AID] = @aid AND [WorkspaceName] = @workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@aid", uid), + new SqlCeParameter("@workspacename", WorkspaceName), + }; + + obj = DB.RunSQLCommandTextExecuteScalar(sql2, sqlparams2); + return (obj != null); + } + } + return false; + } + + /// + /// Uses The workspace stored in the State Table and determines if the Artifact is part of that Workspace + /// + /// Artifact To Check (Location Needed Only) + /// true, if part of the current workspace in the state table, false otherwise + public bool IsArtifactPartOfCurrentWorkspaceState(ArtifactItem artifactItem) + { + // Check validity of the Artifact + if ((artifactItem == null) || + !artifactItem.IsLocationValid) + return false; + + lock(this) + { + string CurrentWorkspace = Data.State.GetCurrentWorkspaceName(); + if (!String.IsNullOrEmpty(CurrentWorkspace)) + { + return IsArtifactPartOfWorkspace(CurrentWorkspace, artifactItem); + } + } + return false; + } + + /// + /// Use this when you have an Artifact that doesn't have any WorkspaceLink Properties and you + /// want to fill the Artifact's WorkspaceLink properties with the first artifact that matches the + /// specified workspace sort order + /// + /// artifactItem without WorkspaceLink Properties (Location Needed Only) + /// SortOrder of workspace to use when filling the first found artifact that matches + /// an artifact item with workspaceLink properties filled out if successfull + public ArtifactItem GetWorkspaceLinkPropertiesForArtifact(ArtifactItem artifactItem, SortOrderForWorkspaces sortOrder) + { + // ensure artifact integrity + if ((artifactItem == null) || + !(artifactItem.IsLocationValid)) + return artifactItem; // nothing filled out + + lock (this) + { + // First Step - Get the UID of the artifact + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + + if (obj != null) + { + int aid = int.Parse(obj.ToString()); + + // Second Step - is to get the WorkspaceLink that matches the artifact by the sort order + string sql2 = "SELECT [WorkspaceLinks].[WindowTop], [WorkspaceLinks].[WindowLeft],[WorkspaceLinks].[WindowHeight], [WorkspaceLinks].[WindowWidth]"; + sql2 = sql2 + " FROM [WorkspaceLinks] , [Workspaces] WHERE [WorkspaceLinks].[WorkspaceName] = [Workspaces].[Name] AND [WorkspaceLinks].[AID]=@aid"; + + // Add WorkspacesSortOrder + sql2 = SortOrderSQLHelpers.SortOrderForWorkspacesHelper(sql2, sortOrder); + + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] { new SqlCeParameter("@aid", aid) }; + + DataSet dataset = DB.RunSQLTextFillDataSet(sql2, sqlparams2); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + // Just get the first item + DataRow datarow = dataset.Tables[0].Rows[0]; + + // Clone the original artifact + ArtifactItem resultArtifact = (ArtifactItem) artifactItem.Clone(); + + // Add Artifact Fields + resultArtifact.WindowTop = int.Parse(datarow["WindowTop"].ToString()); + resultArtifact.WindowLeft = int.Parse(datarow["WindowLeft"].ToString()); + resultArtifact.WindowHeight = int.Parse(datarow["WindowHeight"].ToString()); + resultArtifact.WindowWidth = int.Parse(datarow["WindowWidth"].ToString()); + return resultArtifact; + } + } + } + + // nothing filled out + return artifactItem; + } + + /// + /// Retrieve all Artifacts associated with the specified Workspace (uses links table to determine which artifacts) + /// + /// The WorkspaceName for which to get all Artifacts + /// Specify Sort Order + /// Group of Artifact Items, Could be Empty, use DataTypeValidator to check for Empty ArtifactGroup + public ArtifactItem[] GetAllArtifactsForWorkspace(string WorkspaceName, SortOrderForArtifacts SortBy) + { + // Ensure Workspace Name Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return DataTypeHelpers.EmptyArtifactItemGroup(); // return Blank Item + + lock (this) + { + // Check to make sure that this is a valid WorkspaceName (in DB) + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return DataTypeHelpers.EmptyArtifactItemGroup(); // return Blank Item + + // First Step - Use a Join to get all the matching artifacts + string sql = "SELECT [Artifacts].[Name], [Artifacts].[Type], [Artifacts].[Location], [Artifacts].[Note], [Artifacts].[SnapShotFile], [Artifacts].[LastAccessed], [Artifacts].[AccessCounter], [WorkspaceLinks].[WindowTop], "; + sql = sql + "[WorkspaceLinks].[WindowLeft], [WorkspaceLinks].[WindowHeight], [WorkspaceLinks].[WindowWidth], [WorkspaceLinks].[WorkspaceName] "; + sql = sql + "FROM [WorkspaceLinks] , [Artifacts] "; + sql = sql + "WHERE [WorkspaceLinks].[AID] = [Artifacts].[UID] AND [WorkspaceLinks].[WorkspaceName] = @workspacename "; + + // Add ArtifactsSortOrder + sql = SortOrderSQLHelpers.SortOrderForArtifactsHelper(sql, SortBy); + + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + DataSet dataset = DB.RunSQLTextFillDataSet(sql, sqlparams); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + int nRows = dataset.Tables[0].Rows.Count; + ArtifactItem[] resultArtifacts = new ArtifactItem[nRows]; + + for (int i = 0; i < nRows; ++i) + { + DataRow datarow = dataset.Tables[0].Rows[i]; + resultArtifacts[i] = new ArtifactItem(); + + // Add Artifact Fields + resultArtifacts[i].Name = datarow["Name"].ToString(); + resultArtifacts[i].Type = (ArtifactTypes)Enum.Parse(typeof(ArtifactTypes), datarow["Type"].ToString(), true); + resultArtifacts[i].Location = datarow["Location"].ToString(); + resultArtifacts[i].Note = datarow["Note"].ToString(); + resultArtifacts[i].SnapshotFile = datarow["SnapShotFile"].ToString(); + + if(!String.IsNullOrEmpty(datarow["LastAccessed"].ToString())) + resultArtifacts[i].SetLastAccessed(DateTime.Parse(datarow["LastAccessed"].ToString())); + + if (!String.IsNullOrEmpty(datarow["AccessCounter"].ToString())) + resultArtifacts[i].AccessCounter = int.Parse(datarow["AccessCounter"].ToString()); + + resultArtifacts[i].WindowTop = int.Parse(datarow["WindowTop"].ToString()); + resultArtifacts[i].WindowLeft = int.Parse(datarow["WindowLeft"].ToString()); + resultArtifacts[i].WindowHeight = int.Parse(datarow["WindowHeight"].ToString()); + resultArtifacts[i].WindowWidth = int.Parse(datarow["WindowWidth"].ToString()); + } + return resultArtifacts; + } + + } + + // return Blank Item + return DataTypeHelpers.EmptyArtifactItemGroup(); + } + + /// + /// Get's the artifact link count for the passed in workspace + /// + /// The WorkspaceName for which to get all Artifact Links + /// 0 or positive number for the number of records, -1 if error occurs + public int GetArtifactLinkCountForWorkspace(string WorkspaceName) + { + // Ensure Workspace Name Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return -1; // return error + + lock (this) + { + // Check to make sure that this is a valid WorkspaceName (in DB) + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return -1; // return Blank Item + + // First Step - Get the count of all artifacts for this workspace + string sql = "SELECT COUNT([WorkspaceLinks].[AID]) FROM [WorkspaceLinks] WHERE [WorkspaceLinks].[WorkspaceName] = @workspacename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + if (obj != null) + { + int i = int.Parse(obj.ToString()); + return i; + } + } + return -1; // return error + } + + /// + /// Get's the unique artifact link count for the passed in workspace (this means only artifact links + /// that are unique to this workspace) + /// + /// The WorkspaceName for which to get all unique Artifact Links + /// 0 or positive number for the number of records, -1 if error occurs + public int GetUniqureArtifactsCountForWorkspace(string WorkspaceName) + { + // Ensure Workspace Name Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return -1; // return Blank Item + + lock (this) + { + // Check to make sure that this is a valid WorkspaceName (in DB) + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return -1; // return Blank Item + + // First Step - We need all the links that are part of the workspace in the links table + string sql2 = "SELECT [AID] FROM WorkspaceLinks WHERE [WorkspaceName]=@workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + DataSet dataset = DB.RunSQLTextFillDataSet(sql2, sqlparams2); + List workspaceLinksListAIDs = new List(); + + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + foreach (DataRow row in dataset.Tables[0].Rows) + workspaceLinksListAIDs.Add(int.Parse(row[0].ToString())); + } + + // Second Step - We now should check which AIDs are not referenced anywhere else, those AIDS are + // counted as being unique to this workspace + string sql4 = "SELECT [UID] FROM WorkspaceLinks WHERE [AID]=@aid AND [WorkspaceName]<>@workspacename"; + List workspaceLinksListAIDsWithoutReferences = new List(); + + foreach (int aid in workspaceLinksListAIDs) + { + SqlCeParameter[] sqlparams4 = new SqlCeParameter[] { new SqlCeParameter("@aid", aid), new SqlCeParameter("@workspacename", WorkspaceName) }; + object obj = DB.RunSQLCommandTextExecuteScalar(sql4, sqlparams4); + + if (obj == null) // this aid has no references + workspaceLinksListAIDsWithoutReferences.Add(aid); + } + + return workspaceLinksListAIDsWithoutReferences.Count; + } + } + + /// + /// Adds an Artifact to a Workspace (shouldn't already be in that workspace) + /// If the artifact already exists and the only thing being done is that the artifact is + /// being added to a new workspace (a link will be created) + /// + /// WorkspaceName to insert Artifact into + /// the Artifact to Add (Must be complete - pass All Validations) + /// true if successful, false otherwise + public bool AddArtifactToWorkspace(string WorkspaceName, ArtifactItem artifactItem) + { + // ensure artifact and workspace integrity + if ((artifactItem == null) || + !(artifactItem.IsValid) || + !(artifactItem.IsLocationValid) || + !(artifactItem.IsValidFileIntegrity) || + !(artifactItem.AreWorkspaceLinkPropertiesValid) || + !DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + lock (this) + { + // Check to make sure that this is a valid WorkspaceName + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return false; + + //// + // Do a little more Integrity Checking, to know where we are at + //// + bool bExists = DoesArtifactExistInSystem(artifactItem); + bool bAlreadyInWorkspace = false; + + if(bExists) + bAlreadyInWorkspace = IsArtifactPartOfWorkspace(WorkspaceName, artifactItem); + + // If we already have it in this workspace, just modify the + // Artifact's Properties & Workspace Properties + if (bAlreadyInWorkspace) + return ModifyExistingArtifactProperties(artifactItem, WorkspaceName); // * also modify workspacelink properties * + + // if it exists, but is not part of this workspace, then we should create a link for the artifact and + // update any of the artifact's properties + if (bExists && !bAlreadyInWorkspace) + { + // First Step - Get the UID of the artifact + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + + if (obj != null) + { + int aid = int.Parse(obj.ToString()); + int uid = 0; + + // Second Step - Is to get the Max UID for the Links table to Insert to + string sql2 = "SELECT MAX (UID) FROM WorkspaceLinks"; + object obj2 = DB.RunSQLCommandTextExecuteScalar(sql2); + + if (obj2 != null) + { + uid = int.Parse(obj2.ToString()); + uid = uid + 1; // incr. by one + } + + // Third Step - Create a new Entry for this workspace in the Links Table + string sql3 = "INSERT INTO WorkspaceLinks ([UID],[AID],[WorkspaceName],[WindowTop],[WindowLeft],[WindowHeight],[WindowWidth])"; + sql3 = sql3 + " VALUES (@uid,@aid,@workspacename,@windowtop,@windowleft,@windowheight,@windowwidth)"; + SqlCeParameter[] sqlparams3 = new SqlCeParameter[] + { + new SqlCeParameter("@uid", uid), + new SqlCeParameter("@aid", aid), + new SqlCeParameter("@workspacename", WorkspaceName), + new SqlCeParameter("@windowtop", artifactItem.WindowTop), + new SqlCeParameter("@windowleft", artifactItem.WindowLeft), + new SqlCeParameter("@windowheight", artifactItem.WindowHeight), + new SqlCeParameter("@windowwidth", artifactItem.WindowWidth), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql3, sqlparams3); + if (nResult != 1) + return false; + + // Now we can just Modify the Artifact's Properties, in case they changed + return ModifyExistingArtifactProperties(artifactItem); // no need to modify workspace properties here - only modify artifact + } + } + else + { + + // First Step - Is to get the Max UID for the Artifact table to Insert to + int uid = 0; + string sql = "SELECT MAX (UID) FROM Artifacts"; + object obj = DB.RunSQLCommandTextExecuteScalar(sql); + + if (obj != null) + { + uid = int.Parse(obj.ToString()); + uid = uid + 1; // incr. by one + } + + // Second Step - Is to Actually Insert the new Artifact into the Artifact Table + string sql3 = "INSERT INTO Artifacts ([UID],[Name],[Type],[Location],[Note],[SnapShotFile],[LastAccessed],[AccessCounter]) "; + sql3 = sql3 + "VALUES (@uid,@name,@type,@location,@note,@snapshotfile,@accessed,@counter)"; + SqlCeParameter[] sqlparams3 = new SqlCeParameter[] + { + new SqlCeParameter("@uid", uid), + new SqlCeParameter("@name", artifactItem.Name), + new SqlCeParameter("@type", artifactItem.Type.ToString()), + new SqlCeParameter("@location", artifactItem.Location), + new SqlCeParameter("@note", artifactItem.Note), + new SqlCeParameter("@snapshotfile", artifactItem.SnapshotFile), + new SqlCeParameter("@accessed", DateTime.Now), + new SqlCeParameter("@counter", "0"), + }; + + int nResult = 0; + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql3, sqlparams3); + if (nResult != 1) + return false; + + // Third Step - Get the highest UID for the Link table + int aid = uid; // save the uid of the artifact as the aid + uid = 0; + string sql4 = "SELECT MAX (UID) FROM WorkspaceLinks"; + object obj4 = DB.RunSQLCommandTextExecuteScalar(sql4); + + if (obj != null) + { + uid = int.Parse(obj4.ToString()); + uid = uid + 1; // incr. by one + } + + // Fourth Step - Is to Now Insert the Link to the Workspace into the Links Table + string sql5 = "INSERT INTO WorkspaceLinks ([UID],[AID],[WorkspaceName],[WindowTop],[WindowLeft],[WindowHeight],[WindowWidth]) VALUES (@uid,@aid,@workspacename,@windowtop,@windowleft,@windowheight,@windowwidth)"; + SqlCeParameter[] sqlparams5 = new SqlCeParameter[] + { + new SqlCeParameter("@uid", uid), + new SqlCeParameter("@aid", aid), + new SqlCeParameter("@workspacename", WorkspaceName), + new SqlCeParameter("@windowtop", artifactItem.WindowTop), + new SqlCeParameter("@windowleft", artifactItem.WindowLeft), + new SqlCeParameter("@windowheight", artifactItem.WindowHeight), + new SqlCeParameter("@windowwidth", artifactItem.WindowWidth), + }; + + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql5, sqlparams5); + if (nResult != 1) + return false; + else + return true; + } + } + return false; + } + + /// + /// Deletes Artifact from the workspace (if no more references exists), + /// will delete the artifact entirely (in best scenario only a link will be deleted) + /// + /// WorkspaceName to Delete Artifact From + /// Artifact To Delete (Location Needed Only) + /// true if successful, false otherwise + public bool DeleteArtifact(string WorkspaceName, ArtifactItem artifactItem) + { + // ensure artifact and workspace integrity + if ((artifactItem == null) || + !(artifactItem.IsLocationValid) || + !DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + lock (this) + { + // Check to make sure that this is a valid Artifact + if (!DoesArtifactExistInSystem(artifactItem)) + return false; + + // Check to make sure that this is a valid WorkspaceName + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return false; + + // First Step - Is to get the UID of the Artifact + string sql1 = "SELECT [UID] FROM Artifacts WHERE [Location]=@location"; + SqlCeParameter[] sqlparams1 = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + + object obj = DB.RunSQLCommandTextExecuteScalar(sql1, sqlparams1); + if (obj != null) + { + int uid = int.Parse(obj.ToString()); + + // Second Step - Is to Delete the Link in the Link Table + string sql2 = "DELETE FROM WorkspaceLinks WHERE [WorkspaceName]=@workspacename AND [AID]=@aid"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@workspacename", WorkspaceName) , + new SqlCeParameter("@aid", uid) + }; + + // We hope there at least one link in the links table (but we don't verify) + DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + + // Third Step - Next is to see if there are any other Links Left with this AID + string sql3 = "SELECT [UID] FROM WorkspaceLinks WHERE [AID]=@aid"; + SqlCeParameter[] sqlparams3 = new SqlCeParameter[] { new SqlCeParameter("@aid", uid) }; + + object obj3 = DB.RunSQLCommandTextExecuteScalar(sql3, sqlparams3); + if (obj3 == null) + { + // Fourth Step - Only if there are no other more links, Delete the Actually Artifact from the + // Artifact Table + string sql4 = "DELETE From Artifacts WHERE [UID]=@uid"; + SqlCeParameter[] sqlparams4 = new SqlCeParameter[] { new SqlCeParameter("@uid", uid) }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql4, sqlparams4); + if (nResult != 1) + return false; + else + return true; + } + } + } + return false; + } + + /// + /// Forces Deletion of the Artifact and all Links / References in the System + /// + /// Artifact To Delete (Location Needed Only) + /// true if successful, false otherwise + public bool DeleteArtifact(ArtifactItem artifactItem) + { + // ensure artifact integrity + if ((artifactItem == null) || + !(artifactItem.IsLocationValid)) + return false; + + lock (this) + { + + // Check to make sure that this is a valid Artifact + if (!DoesArtifactExistInSystem(artifactItem)) + return false; + + // First Step - Is to get the UID of the Artifact + string sql1 = "SELECT [UID] FROM Artifacts WHERE [Location]=@location"; + SqlCeParameter[] sqlparams1 = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + + object obj = DB.RunSQLCommandTextExecuteScalar(sql1, sqlparams1); + if (obj != null) + { + int uid = int.Parse(obj.ToString()); + + // Second Step - Is to Delete all the Links refering to the Artifact in the Links Table + string sql2 = "DELETE FROM WorkspaceLinks WHERE [AID]=@aid"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] { new SqlCeParameter("@aid", uid) }; + + DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + + // Third Step - Delete the Artifact from the Artifact Table + string sql3 = "DELETE From Artifacts WHERE [UID]=@uid"; + SqlCeParameter[] sqlparams3 = new SqlCeParameter[] { new SqlCeParameter("@uid", uid) }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql3, sqlparams3); + if (nResult != 1) + return false; + else + return true; + } + } + return false; + } + + /// + /// Modify Properties of an Artifact. Artifact's Location is the Unique Key, + /// it must already exist in the system for this update to work. + /// (this will only update Artifact Properties Not WorkspaceLink Properties) + /// + /// the Artifact to Modify (Must be complete - pass All Validations) + /// true if successful, false otherwise + public bool ModifyExistingArtifactProperties(ArtifactItem artifactItem) + { + // ensure artifact integrity + if ((artifactItem == null) || + !(artifactItem.IsValid) || + !(artifactItem.IsLocationValid) || + !(artifactItem.IsValidFileIntegrity)) + return false; + + object obj = null; + lock (this) + { + // ensure existence + if (!DoesArtifactExistInSystem(artifactItem)) + return false; + + // First Step - Get the UID of the Artifact so that we can update it + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + + if (obj != null) + { + int uid = int.Parse(obj.ToString()); + + // Second Step - Is to Create the Update Statement to update the Artifact + string sql2 = "UPDATE Artifacts SET [Name]=@name,[Type]=@type,[Location]=@location,[Note]=@note,[SnapShotFile]=@snapshotfile, [LastAccessed]=@accessed, [AccessCounter]=@counter "; + sql2 = sql2 + "WHERE [UID]=@uid"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@uid", uid), + new SqlCeParameter("@name", artifactItem.Name), + new SqlCeParameter("@type", artifactItem.Type.ToString()), + new SqlCeParameter("@location", artifactItem.Location), + new SqlCeParameter("@note", artifactItem.Note), + new SqlCeParameter("@snapshotfile", artifactItem.SnapshotFile), + new SqlCeParameter("@accessed", artifactItem.LastAccessed), + new SqlCeParameter("@counter", artifactItem.AccessCounter), + }; + + int nResult = 0; + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + + if (nResult != 1) + return false; + else + return true; + } + } + return false; + } + + /// + /// Modify Properties of an Artifact and the properties of a workspaceLink. + /// Artifact's Location is the Unique Key, it must already exist in the system. + /// + /// the Artifact to Modify (Must be complete - pass All Validations) + /// the workspaceName whose Link properties to modify + /// true if successful, false otherwise + public bool ModifyExistingArtifactProperties(ArtifactItem artifactItem, string WorkspaceName) + { + // ensure artifact and workspace integrity + if ((artifactItem == null) || + !(artifactItem.IsValid) || + !(artifactItem.IsLocationValid) || + !(artifactItem.IsValidFileIntegrity) || + !(artifactItem.AreWorkspaceLinkPropertiesValid) || + !DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + lock (this) + { + // First Step - modify the Artifact's Properties *if fails, return* + if (!ModifyExistingArtifactProperties(artifactItem)) + return false; + + // Now Check Validity of the Workspace Properties before continuing + if (!artifactItem.AreWorkspaceLinkPropertiesValid) + return false; + + // Ensure existence of WorkspaceName + if (!Data.Workspace.DoesWorkspaceNameExist(WorkspaceName)) + return false; + + // Second Step - get the AID for the Artifact + string sql = "SELECT [UID] FROM Artifacts WHERE [Location] = @location"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@location", artifactItem.Location) }; + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + + if (obj != null) + { + int uid = int.Parse(obj.ToString()); + + // Third Step - Is to Update the Workspace Link Properties + string sql2 = "UPDATE WorkspaceLinks SET [WindowTop]=@windowtop,[WindowLeft]=@windowleft,[WindowHeight]=@windowheight,[WindowWidth]=@windowwidth "; + sql2 = sql2 + "WHERE [AID]=@uid AND [WorkspaceName] = @workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@windowtop", artifactItem.WindowTop), + new SqlCeParameter("@windowleft", artifactItem.WindowLeft), + new SqlCeParameter("@windowheight", artifactItem.WindowHeight), + new SqlCeParameter("@windowwidth", artifactItem.WindowWidth), + new SqlCeParameter("@uid", uid), + new SqlCeParameter("@workspacename", WorkspaceName), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + if (nResult != 1) + return false; + else + return true; + } + } + + return false; + } + + } +} diff --git a/DataAccessLayer/dState.cs b/DataAccessLayer/dState.cs new file mode 100644 index 0000000..c8465ad --- /dev/null +++ b/DataAccessLayer/dState.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Data.SqlServerCe; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.DataAccessLayer +{ + public class dState + { + private const string EMPTY_WORKSPACE_NAME_STATE = "____CURRENT__WORKSPACE____IS___SET_TO__NIL__"; + + /// + /// Get the Current WorkspaceName in the State Table + /// + /// the name of the current's state workspace + public string GetCurrentWorkspaceName() + { + object obj = null; + lock (this) + { + string sql = "SELECT [CurrentWorkspaceName] FROM State"; + obj = DB.RunSQLCommandTextExecuteScalar(sql); + } + + if (obj != null) + { + if (obj.ToString() == EMPTY_WORKSPACE_NAME_STATE) + return string.Empty; + else + return obj.ToString(); + } + else + return string.Empty; + } + + /// + /// Set the Current WorkspaceName in the State Table + /// + /// the name of the new workspace name (Can NOT be String.Empty!, use ClearCurrentWorkspaceName() instead) + /// true if successful, false otherwise + public bool SetCurrentWorkspaceName(string currentWorkspaceName) + { + if (!String.IsNullOrEmpty(currentWorkspaceName) && DataTypeValidation.IsValidWorkspaceName(currentWorkspaceName)) + { + lock (this) + { + // Existence Check + if ((currentWorkspaceName != EMPTY_WORKSPACE_NAME_STATE) && + !Data.Workspace.DoesWorkspaceNameExist(currentWorkspaceName)) + return false; + + string currentWorkspaceNameInDB = GetCurrentWorkspaceName(); + + // check if different + bool bIsDifferent = (currentWorkspaceNameInDB.ToLower() != currentWorkspaceName.ToLower()); + if (!bIsDifferent) + return false; + + bool bInsert = !IsInEmptyWorkspaceNameState() && String.IsNullOrEmpty(currentWorkspaceNameInDB); + if (bInsert) + { + string sql = "INSERT INTO State ([CurrentWorkspaceName]) VALUES (@workspacename)"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", currentWorkspaceName) }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + if (nResult != 1) + return false; + else + return true; + } + else + { + string sql = "UPDATE State SET [CurrentWorkspaceName]=@newworkspacename WHERE [CurrentWorkspaceName]=@oldworkspacename"; + SqlCeParameter[] sqlparams; + + if (!IsInEmptyWorkspaceNameState()) + { + sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@oldworkspacename", currentWorkspaceNameInDB), + new SqlCeParameter("@newworkspacename", currentWorkspaceName), + }; + } + else + { + sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@oldworkspacename", EMPTY_WORKSPACE_NAME_STATE), + new SqlCeParameter("@newworkspacename", currentWorkspaceName), + }; + } + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + if (nResult != 1) + return false; + else + return true; + } + } + } + return false; + } + + /// + /// Mostly used internally for the Empty WorkspaceName State + /// + /// true if we are in this state, false otherwise + internal bool IsInEmptyWorkspaceNameState() + { + object obj = null; + lock (this) + { + string sql = "SELECT [CurrentWorkspaceName] FROM State"; + obj = DB.RunSQLCommandTextExecuteScalar(sql); + } + + if (obj != null) + { + if (obj.ToString() == EMPTY_WORKSPACE_NAME_STATE) + return true; + else + return false; + } + else + return false; + } + + /// + /// Clears the current workspace in the State Table + /// + public void ClearCurrentWorkspaceName() + { + SetCurrentWorkspaceName(EMPTY_WORKSPACE_NAME_STATE); + } + } +} diff --git a/DataAccessLayer/dUserSettings.cs b/DataAccessLayer/dUserSettings.cs new file mode 100644 index 0000000..cd66417 --- /dev/null +++ b/DataAccessLayer/dUserSettings.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.SqlServerCe; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.DataAccessLayer +{ + public enum UserSetting + { + ON_LAUNCH_CLOSEPREVIOUS_WORKSPACE, + } + + public class dUserSettings + { + /// + /// Quick Check if there is already a Setting Information available for this Table + /// + /// a Setting enum + /// true if the DB has setting information for this setting + internal bool DoesSettingHaveAnEntry(UserSetting setting) + { + object obj = null; + lock (this) + { + string sql = "SELECT [SettingName] FROM UserSettings WHERE [SettingName] = @settingname"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@settingname", setting.ToString()) }; + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + } + return (obj != null); + } + + /// + /// Retrieve Setting Value for the Setting as a string + /// + /// a Setting enum + /// setting value string, or empty.string if not found + public string GetSettingValueStr(UserSetting setting) + { + object obj = null; + lock (this) + { + string sql = "SELECT [SettingValue] FROM UserSettings WHERE [SettingName] = @settingname"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@settingname", setting.ToString()) }; + + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + if (obj != null) + return obj.ToString(); + } + return String.Empty; + } + + /// + /// Set a Setting Value for the Setting as a string + /// + /// a Setting enum + /// a string value to store for a setting + /// true if successfully inserted or updated, false otherwise + public bool SetSettingValueStr(UserSetting setting, string strSettingValue) + { + // Ensure Value Integrity + if (String.IsNullOrEmpty(strSettingValue)) + return false; + + lock (this) + { + // First Determine if we need to update or insert + bool bUpdate = DoesSettingHaveAnEntry(setting); + + if (!bUpdate) // we need to insert + { + string sql = "INSERT INTO UserSettings ([SettingName],[SettingValue]) VALUES (@settingname,@settingvalue)"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@settingname", setting.ToString()), + new SqlCeParameter("@settingvalue", strSettingValue), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + return (nResult == 1); + } + else // we need to update + { + string sql2 = "UPDATE UserSettings SET [SettingValue]=@settingvalue WHERE [SettingName]=@settingname"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@settingname", setting.ToString()), + new SqlCeParameter("@settingvalue", strSettingValue), + }; + + + int nResult2 = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + return (nResult2 == 1); + } + } + } + + #region Helper Getter/Setters + + public bool GetSettingValueBool(UserSetting setting) + { + try + { + string strValue = GetSettingValueStr(setting); + if(!String.IsNullOrEmpty(strValue)) + { + bool bRet = bool.Parse(strValue); + return bRet; + } + } + catch(Exception){ /* ignore */ } + return false; + } + + public int GetSettingValueInt(UserSetting setting) + { + try + { + string strValue = GetSettingValueStr(setting); + if (!String.IsNullOrEmpty(strValue)) + { + int bRet = int.Parse(strValue); + return bRet; + } + } + catch (Exception) { /* ignore */ } + return int.MinValue; + } + + public DateTime GetSettingValueDateTime(UserSetting setting) + { + try + { + string strValue = GetSettingValueStr(setting); + if (!String.IsNullOrEmpty(strValue)) + { + DateTime bRet = DateTime.Parse(strValue); + return bRet; + } + } + catch (Exception) { /* ignore */ } + return DateTime.MinValue; + } + + public double GetSettingValueDouble(UserSetting setting) + { + try + { + string strValue = GetSettingValueStr(setting); + if (!String.IsNullOrEmpty(strValue)) + { + double bRet = double.Parse(strValue); + return bRet; + } + } + catch (Exception) { /* ignore */ } + return double.MinValue; + } + + public bool SetSettingValueBool(UserSetting setting, bool settingValue) + { + return SetSettingValueStr(setting, settingValue.ToString()); + } + + public bool SetSettingValueInt(UserSetting setting, int settingValue) + { + return SetSettingValueStr(setting, settingValue.ToString()); + } + + public bool SetSettingValueDateTime(UserSetting setting, DateTime settingValue) + { + return SetSettingValueStr(setting, settingValue.ToString()); + } + + public bool SetSettingValueDouble(UserSetting setting, double settingValue) + { + return SetSettingValueStr(setting, settingValue.ToString()); + } + + #endregion + } +} diff --git a/DataAccessLayer/dVersioningTables.cs b/DataAccessLayer/dVersioningTables.cs new file mode 100644 index 0000000..0039fa8 --- /dev/null +++ b/DataAccessLayer/dVersioningTables.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.SqlServerCe; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.DataAccessLayer +{ + internal class dVersioningTables + { + + /// + /// Quick Check if there is Version Information available for this Table + /// + /// a table name to check + /// true if the DB has version information for this Table + internal bool DoesTableHaveVersionEntry(string TableName) + { + // Check TableName Integrity + if (!DataTypeValidation.IsValidTableName(TableName)) + return false; + + object obj = null; + lock (this) + { + string sql = "SELECT [TableName] FROM VersioningTables WHERE [TableName] = @tablename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@tablename", TableName) }; + + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + } + return (obj != null); + } + + /// + /// Retrieve the Version information for the specified Table + /// + /// a table name to check + /// version information string, or empty.string if not found + internal string GetVersionInformationForTable(string TableName) + { + // Check TableName Integrity + if (!DataTypeValidation.IsValidTableName(TableName)) + return String.Empty; + + object obj = null; + lock (this) + { + string sql = "SELECT [Version] FROM VersioningTables WHERE [TableName] = @tablename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@tablename", TableName) }; + + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + if (obj != null) + return obj.ToString(); + } + return String.Empty; + } + + /// + /// Use this most often to insert/update the version information of a table into the VersioningTables Table + /// + /// The table name for which to insert version information + /// the version information in the format of n.n.nnnn + /// true if successfully inserted or updated, false otherwise + internal bool AddUpdateVersionInformationForSpecifiedTable(string TableName, string VersionInformation) + { + // Check TableName Integrity + if (!DataTypeValidation.IsValidTableName(TableName)) + return false; + + // Check Version Integrity + if (!DataTypeValidation.IsValidVersionInformation(VersionInformation)) + return false; + + lock (this) + { + // First Determine if we need to update or insert + bool bUpdate = DoesTableHaveVersionEntry(TableName); + + if (!bUpdate) // we need to insert + { + string sql = "INSERT INTO VersioningTables ([TableName],[Version]) VALUES (@tablename,@version)"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@tablename", TableName), + new SqlCeParameter("@version", VersionInformation), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + return (nResult == 1); + } + else // we need to update + { + string sql2 = "UPDATE VersioningTables SET [Version]=@version WHERE [TableName]=@tablename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@tablename", TableName), + new SqlCeParameter("@version", VersionInformation), + }; + + + int nResult2 = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + return (nResult2 == 1); + } + } + } + } +} diff --git a/DataAccessLayer/dWorkspace.cs b/DataAccessLayer/dWorkspace.cs new file mode 100644 index 0000000..e2a46f6 --- /dev/null +++ b/DataAccessLayer/dWorkspace.cs @@ -0,0 +1,341 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Data.SqlServerCe; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.DataAccessLayer +{ + public class dWorkspace + { + + /// + /// Quick Check to see If the WorkspaceName already exists + /// + /// Name of Workspace + /// true if Name exists, false otherwise + public bool DoesWorkspaceNameExist(string WorkspaceName) + { + // Check WorkspaceName Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + object obj = null; + lock (this) + { + string sql = "SELECT [Name] FROM Workspaces WHERE [Name] = @workspacename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + } + return (obj != null); + } + + /// + /// Retrieve a String list of all WorkspaceNames in the Database + /// + /// Specify the SortOrder of the List + /// a list of worspace names, or empty[] if none exist + public string[] GetAllWorkspaceNames(SortOrderForWorkspaces SortBy) + { + List resultList = new List(); + lock (this) + { + string sql = "SELECT [Name] FROM Workspaces"; + + // Add WorkspaceSortOrder + sql = SortOrderSQLHelpers.SortOrderForWorkspacesHelper(sql, SortBy); + + DataSet dataset = DB.RunSQLTextFillDataSet(sql); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + foreach (DataRow row in dataset.Tables[0].Rows) + resultList.Add(row[0].ToString()); + } + } + return resultList.ToArray(); + } + + /// + /// Retrieve a Workspace List of all Workspaces in the Database + /// + /// Specify the SortOrder of the List + /// a list of worspaces + public WorkspaceItem[] GetAllWorkspaces(SortOrderForWorkspaces SortBy) + { + List resultList = new List(); + lock (this) + { + string sql = "SELECT [Name],[LastAccessed],[AccessCounter] FROM Workspaces"; + + // Add WorkspaceSortOrder + sql = SortOrderSQLHelpers.SortOrderForWorkspacesHelper(sql, SortBy); + + DataSet dataset = DB.RunSQLTextFillDataSet(sql); + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + int nRows = dataset.Tables[0].Rows.Count; + WorkspaceItem[] resultWorkspaces = new WorkspaceItem[nRows]; + + for (int i = 0; i < nRows; ++i) + { + DataRow datarow = dataset.Tables[0].Rows[i]; + resultWorkspaces[i] = new WorkspaceItem(); + + // Add Workspace Fields + resultWorkspaces[i].Name = datarow["Name"].ToString(); + + if (!String.IsNullOrEmpty(datarow["LastAccessed"].ToString())) + resultWorkspaces[i].SetLastAccessed(DateTime.Parse(datarow["LastAccessed"].ToString())); + + if (!String.IsNullOrEmpty(datarow["AccessCounter"].ToString())) + resultWorkspaces[i].AccessCounter = int.Parse(datarow["AccessCounter"].ToString()); + } + + return resultWorkspaces; + } + } + + // return Blank Item + return DataTypeHelpers.EmptyWorkspaceItemGroup(); + } + + /// + /// Use this to modify a workspace Item (allows you to modify a workspace's properties NOT the name) + /// + /// a workspaceItem whose properties you want to update (Must pass all validations) + /// true if succesfully updated, false otherwise + public bool ModifyWorkspaceItem(WorkspaceItem workspaceItem) + { + // Check WorkspaceName Integrity + if ((workspaceItem == null) || + !workspaceItem.IsValid) + return false; + + lock (this) + { + // existence check + if (!DoesWorkspaceNameExist(workspaceItem.Name)) + return false; + + // First Step - is to create the update statement to make the neccessary modifications + string sql2 = "UPDATE Workspaces SET [LastAccessed]=@lastaccessed,[AccessCounter]=@accesscounter WHERE [Name]=@workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@accesscounter", workspaceItem.AccessCounter), + new SqlCeParameter("@lastaccessed", workspaceItem.LastAccessed), + new SqlCeParameter("@workspacename", workspaceItem.Name), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + return (nResult == 1); + } + } + + /// + /// Increments the access counter and sets LastAccessed for the + /// specified workspace name. Call this whenever you have launched a workspace. + /// + /// an existing workspace Name + /// true if successful set the internal counters, false otherwise + public bool WorkspaceWasLaunched(string WorkspaceName) + { + // Check WorkspaceName Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + lock (this) + { + // existence check + if (!DoesWorkspaceNameExist(WorkspaceName)) + return false; + + // First Step - is to get the AccessCounter already in the db + string sql = "SELECT [AccessCounter] FROM Workspaces WHERE [Name]=@workspacename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + int accesscount = 1; + object obj = DB.RunSQLCommandTextExecuteScalar(sql, sqlparams); + if (obj != null) + { + accesscount = int.Parse(obj.ToString()); + accesscount = accesscount + 1; // increment by 1 + } + + // Second Step - is to set the access counter and today's date for the workspace + string sql2 = "UPDATE Workspaces SET [LastAccessed]=@lastaccessed,[AccessCounter]=@accesscounter WHERE [Name]=@workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@lastaccessed", DateTime.Now), + new SqlCeParameter("@accesscounter", accesscount), + new SqlCeParameter("@workspacename", WorkspaceName), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + return (nResult == 1); + } + } + + /// + /// Inserts a new WorspaceName into the Workspace Table (if it not already exists) + /// + /// new non-existing unique workspace Name + /// true if successful, false otherwise + public bool InsertWorkspaceName(string WorkspaceName) + { + // Check WorkspaceName Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + int nResult = -1; + lock (this) + { + // ensure uniqueness + if (DoesWorkspaceNameExist(WorkspaceName)) + return false; + + string sql = "INSERT INTO Workspaces ([Name],[LastAccessed],[AccessCounter]) VALUES (@workspacename,@accessed,@count)"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@workspacename",WorkspaceName), + new SqlCeParameter("@accessed",DateTime.Now), + new SqlCeParameter("@count","0"), + }; + + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + } + return (nResult == 1); + } + + /// + /// Renames a Workspace to a new Name. In order to do so, we must also rename + /// all possible links that exists, so this process is a two-step process + /// + /// + /// + /// true if successful, false otherwise + public bool RenameWorkspace(string OldWorkspaceName, string NewWorkspaceName) + { + // Check WorkspaceName Integrity + if (!DataTypeValidation.IsValidWorkspaceName(OldWorkspaceName) || + !DataTypeValidation.IsValidWorkspaceName(NewWorkspaceName)) + return false; + + lock (this) + { + // ensure existence + if (!DoesWorkspaceNameExist(OldWorkspaceName)) + return false; + + // First Step - update Workspace Table + string sql = "UPDATE Workspaces SET [Name]=@newworkspacename WHERE [Name]=@oldworkspacename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] + { + new SqlCeParameter("@oldworkspacename", OldWorkspaceName), + new SqlCeParameter("@newworkspacename", NewWorkspaceName), + }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + if (nResult != 1) + return false; + + // Second Step - update Links Table (any links that point to this workspace) + string sql2 = "UPDATE WorkspaceLinks SET [WorkspaceName]=@newworkspacename WHERE [WorkspaceName]=@oldworkspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] + { + new SqlCeParameter("@oldworkspacename", OldWorkspaceName), + new SqlCeParameter("@newworkspacename", NewWorkspaceName), + }; + + int nResult2 = DB.RunSQLCommandTextExecuteNonQuery(sql2, sqlparams2); + if (nResult2 >= 0) + return true; + else + return false; + } + } + + /// + /// Deletes a Workspace. In order to do so, we must also delete and links + /// that the Workspace has. When Deleting links and encountering a link to + /// an artifact that is not references anywhere, we should delete the artifact + /// as well. So this is a five-step process. + /// + /// an existing workspace name + /// true if successful, false otherwise + public bool DeleteWorkspace(string WorkspaceName) + { + // Check WorkspaceName Integrity + if (!DataTypeValidation.IsValidWorkspaceName(WorkspaceName)) + return false; + + lock (this) + { + // ensure existence + if (!DoesWorkspaceNameExist(WorkspaceName)) + return false; + + // First Step - delete WorkspaceName from Workspace Table + string sql = "DELETE FROM Workspaces WHERE [Name]=@workspacename"; + SqlCeParameter[] sqlparams = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + int nResult = DB.RunSQLCommandTextExecuteNonQuery(sql, sqlparams); + if (nResult != 1) + return false; + + // Second Step - We need all the links that are part of the workspace in the links table + string sql2 = "SELECT [AID] FROM WorkspaceLinks WHERE [WorkspaceName]=@workspacename"; + SqlCeParameter[] sqlparams2 = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + DataSet dataset = DB.RunSQLTextFillDataSet(sql2, sqlparams2); + List workspaceLinksListAIDs = new List(); + + if (!DataTypeValidation.IsEmptyDataSet(dataset)) + { + foreach (DataRow row in dataset.Tables[0].Rows) + workspaceLinksListAIDs.Add(int.Parse(row[0].ToString())); + } + + // Third Step - We now have all the AIDs to look later so we can now delete all the links for this + // workspace from the links table + string sql3 = "DELETE FROM WorkspaceLinks WHERE [WorkspaceName]=@workspacename"; + SqlCeParameter[] sqlparams3 = new SqlCeParameter[] { new SqlCeParameter("@workspacename", WorkspaceName) }; + + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql3, sqlparams3); + if (nResult == -1) + return false; + + // Fourth Step - We now should check which AIDs are still referenced in the Link table, those that + // still have references, we keep, others we want to delete + string sql4 = "SELECT [UID] FROM WorkspaceLinks WHERE [AID]=@aid"; + List workspaceLinksListAIDsWithoutReferences = new List(); + + foreach (int aid in workspaceLinksListAIDs) + { + SqlCeParameter[] sqlparams4 = new SqlCeParameter[] { new SqlCeParameter("@aid", aid) }; + object obj = DB.RunSQLCommandTextExecuteScalar(sql4, sqlparams4); + + if (obj == null) // this aid has no references + workspaceLinksListAIDsWithoutReferences.Add(aid); + } + + // Fifth Step - Now we want to delete all artifacts in the artifact table that have no references + // Since we already deleted all links, and workspaces, we should just directly delete the dangling + // Artifacts here + string sql5 = "DELETE FROM Artifacts WHERE [UID]=@uid"; + foreach (int aid in workspaceLinksListAIDsWithoutReferences) + { + SqlCeParameter[] sqlparam5 = new SqlCeParameter[]{ new SqlCeParameter("@uid", aid) }; + nResult = DB.RunSQLCommandTextExecuteNonQuery(sql5, sqlparam5); + + if (nResult != 1) // we expect there to be an artifact to delete + return false; + } + } + return true; + } + + } +} diff --git a/DataAccessLayer/nUnitTests.cs b/DataAccessLayer/nUnitTests.cs new file mode 100644 index 0000000..44e6211 --- /dev/null +++ b/DataAccessLayer/nUnitTests.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; + +using Foo.DataAccessLayer; +using DataAccessLayer.TestData; + +namespace Foo.DataAccessLayer +{ + [TestFixture] + public class nUnitTests + { + + [SetUp] + public void Setup() + { + } + + [TearDown] + public void TearDown() + { + } + + [Test] + public void RecreateDatabaseAndLoadWithDefaultTestData() + { + // First Delete the DB, if it exists + DB.DeleteDefaultDB(); + + // Now Fill the DB with the Test Data + TestData.FillDBWithTestData(); + } + } +} diff --git a/Deskband/BandObjectBase/Attributes.cs b/Deskband/BandObjectBase/Attributes.cs new file mode 100644 index 0000000..7031052 --- /dev/null +++ b/Deskband/BandObjectBase/Attributes.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.InteropServices; +using System.Reflection; + +namespace Foo.Deskband.BandObject +{ + /// + /// Represents different styles of a band object. + /// + [Flags] + [Serializable] + public enum BandObjectStyle : uint + { + Vertical = 1, + Horizontal = 2, + ExplorerToolbar = 4, + TaskbarToolBar = 8 + } + + /// + /// Specifies Style of the band object, its Name(displayed in explorer menu) and HelpText(displayed in status bar when menu command selected). + /// + [AttributeUsage(AttributeTargets.Class)] + public class BandObjectAttribute : System.Attribute + { + public BandObjectAttribute(){} + + public BandObjectAttribute(string name, BandObjectStyle style) + { + Name = name; + Style = style; + } + public BandObjectStyle Style; + public string Name; + public string HelpText; + } +} \ No newline at end of file diff --git a/Deskband/BandObjectBase/BandObject.cs b/Deskband/BandObjectBase/BandObject.cs new file mode 100644 index 0000000..b96febe --- /dev/null +++ b/Deskband/BandObjectBase/BandObject.cs @@ -0,0 +1,476 @@ +using System; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using SHDocVw; +using System.Reflection; +using System.Diagnostics; +using System.Drawing; +using System.ComponentModel; +using Microsoft.Win32; + +using System.Runtime.InteropServices; + +[assembly: AssemblyVersion("1.0.0.0")] + +namespace Foo.Deskband.BandObject +{ + /// + /// Contains main desk band functionality + /// + /// + /// + public class BandObjectBase : UserControl, IObjectWithSite, IDeskBand, IDeskBand2, IDockingWindow, IOleWindow, IInputObject + { + [DllImport("user32.dll")] + public static extern Int32 GetWindowLong(IntPtr hwnd, int nIndex); + + [DllImport("user32.dll")] + public static extern Int32 SetWindowLong(IntPtr hwnd, int nIndex, Int32 dwNewLong); + + [DllImport("user32.dll")] + public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, Int32 crKey, int bAlpha, uint dwFlags); + + public const int GWL_EXSTYLE = -20; + public const int LWA_COLORKEY = 0x00000001; + public const int WS_EX_LAYERED = 0x00080000; + + [StructLayout(LayoutKind.Sequential)] + struct COLORREF + { + public byte R; + public byte G; + public byte B; + } + + public BandObjectBase() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + this.SuspendLayout(); + // + // BandObjectBase + // + this.BackColor = System.Drawing.Color.Black; + this.Margin = new System.Windows.Forms.Padding(0); + this.Name = "BandObjectBase"; + this.Size = new System.Drawing.Size(24, 24); + this.MinimumSize = new System.Drawing.Size(24, 24); + this.MaximumSize = new System.Drawing.Size(24, 24); + this.ResumeLayout(false); + this.HandleCreated += new System.EventHandler(Band_HandleCreated); + this.HandleDestroyed += new System.EventHandler(Band_HandleDestroyed); + } + + private void Band_HandleCreated(object sender, EventArgs e) + { + IntPtr hWnd = this.Handle; + SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); + SetLayeredWindowAttributes(hWnd, 0x00000000, 0, LWA_COLORKEY); + } + + private void Band_HandleDestroyed(object sender, EventArgs e) + { + + } + + #region IObjectWithSite + + public virtual void GetSite(ref Guid riid, out Object ppvSite) + { + ppvSite = BandObjectSite; + } + + public virtual void SetSite(Object pUnkSite) + { + if (BandObjectSite != null) + Marshal.ReleaseComObject(BandObjectSite); + + if (Explorer != null) + { + Marshal.ReleaseComObject(Explorer); + Explorer = null; + } + + BandObjectSite = (IInputObjectSite)pUnkSite; + if (BandObjectSite != null) + { + //pUnkSite is a pointer to object that implements IOleWindowSite or something similar + //we need to get access to the top level object - explorer itself + //to allows this explorer objects also implement IServiceProvider interface + //(don't mix it with System.IServiceProvider!) + //we get this interface and ask it to find WebBrowserApp + _IServiceProvider sp = BandObjectSite as _IServiceProvider; + Guid guid = ExplorerGUIDs.IID_IWebBrowserApp; + Guid riid = ExplorerGUIDs.IID_IUnknown; + + try + { + object w; + sp.QueryService( + ref guid, + ref riid, + out w); + + //once we have interface to the COM object we can create RCW from it + Explorer = (WebBrowserClass)Marshal.CreateWrapperOfType( + w as IWebBrowser, + typeof(WebBrowserClass) + ); + + OnExplorerAttached(EventArgs.Empty); + } + catch (COMException) + { + //we anticipate this exception in case our object instantiated + //as a Desk Band. There is no web browser service available. + } + } + } + + #endregion + + #region IDeskband + + public virtual void GetWindow(out System.IntPtr phwnd) + { + phwnd = Handle; + } + + public virtual void ContextSensitiveHelp(bool fEnterMode){} + + /// + /// Called by explorer when band object needs to be showed or hidden. + /// + /// + public virtual void ShowDW(bool fShow) + { + if (fShow) + Show(); + else + Hide(); + } + + /// + /// Called by explorer when window is about to close. + /// + public virtual void CloseDW(UInt32 dwReserved) + { + Dispose(true); + } + + /// + /// Not used. + /// + public virtual void ResizeBorderDW(IntPtr prcBorder, Object punkToolbarSite, bool fReserved) { } + + public virtual void GetBandInfo(UInt32 dwBandID, UInt32 dwViewMode, ref DESKBANDINFO dbi) + { + + if ((dbi.dwMask & DBIM.MINSIZE) != 0) + { + dbi.ptMinSize.X = MinSize.Width; + dbi.ptMinSize.Y = MinSize.Height; + } + + if ((dbi.dwMask & DBIM.MAXSIZE) != 0) + { + dbi.ptMaxSize.X = MaxSize.Width; + dbi.ptMaxSize.Y = MaxSize.Height; + } + + if ((dbi.dwMask & DBIM.INTEGRAL) != 0) + { + dbi.ptIntegral.X = IntegralSize.Width; + dbi.ptIntegral.Y = IntegralSize.Height; + } + + if ((dbi.dwMask & DBIM.ACTUAL) != 0) + { + dbi.ptActual.X = Size.Width; + dbi.ptActual.Y = Size.Height; + } + + if ((dbi.dwMask & DBIM.TITLE) != 0) + { + dbi.wszTitle = Title; + } + + //Use the default background color by removing this flag + dbi.dwMask &= ~DBIM.BKCOLOR; + + //COLORREF bkColor; + //bkColor.R = Color.Black.R; + //bkColor.G = Color.Black.G; + //bkColor.B = Color.Black.B; + //Color.to + //dbi.crBkgnd = Int32.MaxValue; + //dbi.crBkgnd = 0xDEDEDE; + + dbi.dwModeFlags = (DBIMF)DBIM.TITLE | (DBIMF)DBIM.ACTUAL | (DBIMF)DBIM.MAXSIZE | (DBIMF)DBIM.MINSIZE | (DBIMF)DBIM.INTEGRAL; + dbi.dwModeFlags = dbi.dwModeFlags | DBIMF.ALWAYSGRIPPER | DBIMF.VARIABLEHEIGHT | DBIMF.ADDTOFRONT; + } + + #endregion + + #region IDeskBand2 + + public void CanRenderComposited(ref bool pfCanRenderComposited) + { + pfCanRenderComposited = true; + } + + public void GetCompositionState(ref bool pfCompositionEnabled) + { + pfCompositionEnabled = _compositionEnabled; + } + + public void SetCompositionState(bool fCompositionEnabled) + { + _compositionEnabled = fCompositionEnabled; + } + + #endregion + + #region IInputObject + + /// + /// Called explorer when focus has to be chenged. + /// + public virtual void UIActivateIO(Int32 fActivate, ref MSG Msg) + { + if( fActivate != 0 ) + { + Control ctrl = GetNextControl(this,true);//first + if( ModifierKeys == Keys.Shift ) + ctrl = GetNextControl(ctrl,false );//last + + if( ctrl != null ) ctrl.Select(); + this.Focus(); + } + } + + public virtual Int32 HasFocusIO() + { + return this.ContainsFocus ? 0 : 1; //S_OK : S_FALSE; + } + + /// + /// Called by explorer to process keyboard events. Undersatands Tab and F6. + /// + /// + /// S_OK if message was processed, S_FALSE otherwise. + public virtual Int32 TranslateAcceleratorIO(ref MSG msg) + { + if( msg.message == 0x100 )//WM_KEYDOWN + if( msg.wParam == (uint)Keys.Tab || msg.wParam == (uint)Keys.F6 )//keys used by explorer to navigate from control to control + if( SelectNextControl( + ActiveControl, + ModifierKeys == Keys.Shift ? false : true, + true, + true, + false ) + ) + return 0;//S_OK + + return 1;//S_FALSE + } + + #endregion + + #region EventHandlers + + /// + /// Override this method to handle ExplorerAttached event. + /// + /// + protected virtual void OnExplorerAttached(EventArgs ea) + { + if ( ExplorerAttached != null ) + ExplorerAttached(this, ea); + } + + /// + /// Notifies explorer of focus change. + /// + protected override void OnGotFocus(System.EventArgs e) + { + base.OnGotFocus(e); + BandObjectSite.OnFocusChangeIS(this as IInputObject, 1); + } + /// + /// Notifies explorer of focus change. + /// + protected override void OnLostFocus(System.EventArgs e) + { + base.OnLostFocus(e); + if( ActiveControl == null ) + BandObjectSite.OnFocusChangeIS(this as IInputObject, 0); + } + + #endregion + + #region COM_Bookkeeping + + /// + /// Called when derived class is registered as a COM server. + /// + [ComRegisterFunctionAttribute] + public static void Register(Type t) + { + string guid = t.GUID.ToString("B"); + + RegistryKey rkClass = Registry.ClassesRoot.CreateSubKey(@"CLSID\"+guid ); + RegistryKey rkCat = rkClass.CreateSubKey("Implemented Categories"); + + BandObjectAttribute[] boa = (BandObjectAttribute[])t.GetCustomAttributes( + typeof(BandObjectAttribute), + false ); + + string name = t.Name; + string help = t.Name; + BandObjectStyle style = 0; + if( boa.Length == 1 ) + { + if( boa[0].Name != null ) + name = boa[0].Name; + + if( boa[0].HelpText != null ) + help = boa[0].HelpText; + + style = boa[0].Style; + } + + rkClass.SetValue(null, name ); + rkClass.SetValue("MenuText", name ); + rkClass.SetValue("HelpText", help ); + + if( 0 != (style & BandObjectStyle.Vertical) ) + rkCat.CreateSubKey("{00021493-0000-0000-C000-000000000046}"); + + if( 0 != (style & BandObjectStyle.Horizontal) ) + rkCat.CreateSubKey("{00021494-0000-0000-C000-000000000046}"); + + if( 0 != (style & BandObjectStyle.TaskbarToolBar) ) + rkCat.CreateSubKey("{00021492-0000-0000-C000-000000000046}"); + + if( 0 != (style & BandObjectStyle.ExplorerToolbar) ) + Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Toolbar").SetValue(guid,name); + + } + + /// + /// Called when derived class is unregistered as a COM server. + /// + [ComUnregisterFunctionAttribute] + public static void Unregister(Type t) + { + string guid = t.GUID.ToString("B"); + BandObjectAttribute[] boa = (BandObjectAttribute[])t.GetCustomAttributes( + typeof(BandObjectAttribute), + false ); + + BandObjectStyle style = 0; + if( boa.Length == 1 ) style = boa[0].Style; + + if( 0 != (style & BandObjectStyle.ExplorerToolbar) ) + Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Toolbar").DeleteValue(guid,false); + + Registry.ClassesRoot.CreateSubKey(@"CLSID").DeleteSubKeyTree(guid); + } + + #endregion + + #region Properties + + /// + /// Title of band object. Displayed at the left or on top of the band object. + /// + [Browsable(true)] + [DefaultValue("")] + public String Title + { + get + { + return _title; + } + set + { + _title = value; + } + } + + /// + /// Minimum size of the band object. Default value of -1 sets no minimum constraint. + /// + [Browsable(true)] + [DefaultValue(typeof(Size), "-1,-1")] + public Size MinSize + { + get + { + return _minSize; + } + set + { + _minSize = value; + } + } + + /// + /// Maximum size of the band object. Default value of -1 sets no maximum constraint. + /// + [Browsable(true)] + [DefaultValue(typeof(Size), "-1,-1")] + public Size MaxSize + { + get + { + return _maxSize; + } + set + { + _maxSize = value; + } + } + + /// + /// Says that band object's size must be multiple of this size. Defauilt value of -1 does not set this constraint. + /// + [Browsable(true)] + [DefaultValue(typeof(Size), "-1,-1")] + public Size IntegralSize + { + get + { + return _integralSize; + } + set + { + _integralSize = value; + } + } + + #endregion + + #region Member Variables + + /// + /// This event is fired after reference to hosting explorer is retreived and stored in Explorer property. + /// + public event EventHandler ExplorerAttached; + + protected WebBrowserClass Explorer; + protected IInputObjectSite BandObjectSite; + + private bool _compositionEnabled = true; + private String _title; + private Size _minSize = new Size(-1, -1); + private Size _integralSize = new Size(-1, -1); + private Size _maxSize = new Size(-1, -1); + + #endregion + } +} \ No newline at end of file diff --git a/Deskband/BandObjectBase/BandObject.csproj b/Deskband/BandObjectBase/BandObject.csproj new file mode 100644 index 0000000..488dc6f --- /dev/null +++ b/Deskband/BandObjectBase/BandObject.csproj @@ -0,0 +1,157 @@ + + + Local + 9.0.30729 + 2.0 + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} + Debug + AnyCPU + + + + + Foo.BandObject + BandObjects.snk + JScript + Grid + IE50 + false + Library + Foo.Deskband.BandObject + + + + + 0.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + true + + + + + + + + + + + ..\..\Target\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + false + false + false + 4 + full + prompt + + + ..\..\Target\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + true + false + false + false + 4 + none + prompt + + + + System + + + System.Drawing + + + System.Windows.Forms + + + + + Code + + + UserControl + + + Code + + + BandObject.cs + Designer + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B} + 1 + 1 + 0 + tlbimp + False + + + + + + + + + + "$(FrameworkSDKDir)bin\gacutil.exe" /if "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" +"$(FrameworkSDKDir)bin\gacutil.exe" /if "$(SolutionDir)target\$(ConfigurationName)\Interop.SHDocVw.dll" + + + \ No newline at end of file diff --git a/Deskband/BandObjectBase/BandObject.resx b/Deskband/BandObjectBase/BandObject.resx new file mode 100644 index 0000000..ff31a6d --- /dev/null +++ b/Deskband/BandObjectBase/BandObject.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Deskband/BandObjectBase/BandObjectBase.sln b/Deskband/BandObjectBase/BandObjectBase.sln new file mode 100644 index 0000000..09953a4 --- /dev/null +++ b/Deskband/BandObjectBase/BandObjectBase.sln @@ -0,0 +1,55 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BandObjectLib", "BandObjectLib.csproj", "{BDB3B670-A17B-483E-954C-52FC2B6FF9D3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegisterLib", "RegisterLib\RegisterLib.vcproj", "{E35915FE-ED91-4AE5-B566-F269CD854498}" + ProjectSection(ProjectDependencies) = postProject + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} = {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} + EndProjectSection +EndProject +Global + GlobalSection(TeamFoundationVersionControl) = preSolution + SccNumberOfProjects = 3 + SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} + SccTeamFoundationServer = http://myhome.romischer.com:8080/ + SccLocalPath0 = . + SccProjectUniqueName1 = BandObjectLib.csproj + SccLocalPath1 = . + SccProjectUniqueName2 = RegisterLib\\RegisterLib.vcproj + SccProjectName2 = RegisterLib + SccLocalPath2 = RegisterLib + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Win32.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Win32.ActiveCfg = Release|Any CPU + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Win32.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Win32.Build.0 = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Any CPU.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Mixed Platforms.Build.0 = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Win32.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Deskband/BandObjectBase/BandObjects.snk b/Deskband/BandObjectBase/BandObjects.snk new file mode 100644 index 0000000..87ebce5 Binary files /dev/null and b/Deskband/BandObjectBase/BandObjects.snk differ diff --git a/Deskband/BandObjectBase/ComInterop.cs b/Deskband/BandObjectBase/ComInterop.cs new file mode 100644 index 0000000..f09d526 --- /dev/null +++ b/Deskband/BandObjectBase/ComInterop.cs @@ -0,0 +1,246 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace Foo.Deskband.BandObject +{ + + abstract class ExplorerGUIDs + { + public static readonly Guid IID_IWebBrowserApp = new Guid("{0002DF05-0000-0000-C000-000000000046}"); + public static readonly Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}"); + } + + [Flags] + public enum DBIM : uint + { + MINSIZE = 0x0001, + MAXSIZE = 0x0002, + INTEGRAL = 0x0004, + ACTUAL = 0x0008, + TITLE = 0x0010, + MODEFLAGS = 0x0020, + BKCOLOR = 0x0040, + } + + [Flags] + public enum DBIMF : uint + { + NORMAL = 0x0001, + FIXED = 0x0002, + FIXEDBMP = 0x0004, + VARIABLEHEIGHT = 0x0008, + UNDELETEABLE = 0x0010, + DEBOSSED = 0x0020, + BKCOLOR = 0x0040, + USECHEVRON = 0x0080, + BREAK = 0x0100, + ADDTOFRONT = 0x0200, + TOPALIGN = 0x0400, + NOGRIPPER = 0x0800, + ALWAYSGRIPPER = 0x1000, + NOMARGINS = 0x2000, + } + + [Flags] + public enum DBIF : uint + { + VIEWMODE_NORMAL = 0x0000, + VIEWMODE_VERTICAL = 0x0001, + VIEWMODE_FLOATING = 0x0002, + VIEWMODE_TRANSPARENT = 0x0004 + } + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] + public struct DESKBANDINFO + { + public DBIM dwMask; + public Point ptMinSize; + public Point ptMaxSize; + public Point ptIntegral; + public Point ptActual; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)] + public String wszTitle; + public DBIMF dwModeFlags; + public Int32 crBkgnd; + }; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct CMINVOKECOMMANDINFO + { + uint cbSize; + uint fMask; + IntPtr hwnd; + string lpVerb; + string lpParameters; + string lpDirectory; + int nShow; + uint dwHotKey; + IntPtr hIcon; + }; + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")] + public interface IObjectWithSite + { + void SetSite([In ,MarshalAs(UnmanagedType.IUnknown)] Object pUnkSite); + void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out Object ppvSite); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("00000114-0000-0000-C000-000000000046")] + public interface IOleWindow + { + void GetWindow(out System.IntPtr phwnd); + void ContextSensitiveHelp([In] bool fEnterMode); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("012dd920-7b26-11d0-8ca9-00a0c92dbfe8")] + public interface IDockingWindow + { + void GetWindow(out System.IntPtr phwnd); + void ContextSensitiveHelp([In] bool fEnterMode); + + void ShowDW([In] bool fShow); + void CloseDW([In] UInt32 dwReserved); + void ResizeBorderDW( + IntPtr prcBorder, + [In, MarshalAs(UnmanagedType.IUnknown)] Object punkToolbarSite, + bool fReserved); + } + + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("EB0FE172-1A3A-11D0-89B3-00A0C90A90AC")] + public interface IDeskBand + { + void GetWindow(out System.IntPtr phwnd); + void ContextSensitiveHelp([In] bool fEnterMode); + + void ShowDW([In] bool fShow); + void CloseDW([In] UInt32 dwReserved); + + void ResizeBorderDW( + IntPtr prcBorder, + [In, MarshalAs(UnmanagedType.IUnknown)] Object punkToolbarSite, + bool fReserved); + + void GetBandInfo( + UInt32 dwBandID, + UInt32 dwViewMode, + ref DESKBANDINFO pdbi); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + [Guid("79D16DE4-ABEE-4021-8D9D-9169B261D657")] + public interface IDeskBand2 + { + void GetBandInfo(UInt32 dwBandID, UInt32 dwViewMode, ref DESKBANDINFO pdbi); + + void CanRenderComposited(ref bool pfCanRenderComposited); + + void GetCompositionState(ref bool pfCompositionEnabled); + + void SetCompositionState([MarshalAs(UnmanagedType.Bool)] bool fCompositionEnabled); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("0000010c-0000-0000-C000-000000000046")] + public interface IPersist + { + void GetClassID(out Guid pClassID); + } + + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("00000109-0000-0000-C000-000000000046")] + public interface IPersistStream + { + void GetClassID(out Guid pClassID); + + void IsDirty (); + + void Load ([In, MarshalAs(UnmanagedType.Interface)] Object pStm); + + void Save ([In, MarshalAs(UnmanagedType.Interface)] Object pStm, + [In] bool fClearDirty); + + void GetSizeMax ([Out] out UInt64 pcbSize); + } + + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] + public interface _IServiceProvider + { + void QueryService( + ref Guid guid, + ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out Object Obj); + } + + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("68284faa-6a48-11d0-8c78-00c04fd918b4")] + public interface IInputObject + { + void UIActivateIO(Int32 fActivate, ref MSG msg); + + [PreserveSig] + //[return:MarshalAs(UnmanagedType.Error)] + Int32 HasFocusIO(); + + [PreserveSig] + Int32 TranslateAcceleratorIO(ref MSG msg); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214e4-0000-0000-c000-000000000046")] + public interface IContextMenu + { + [PreserveSig()] + int QueryContextMenu(uint hmenu, uint indexMenu, int idCmdFirst, int idCmdLast, uint uFlags); + [PreserveSig()] + void InvokeCommand (IntPtr pici); + [PreserveSig()] + void GetCommandString(int idCmd, uint uFlags, int reserved, string name, int cchMax); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("f1db8392-7331-11d0-8c99-00a0c92dbfe8")] + public interface IInputObjectSite + { + [PreserveSig] + Int32 OnFocusChangeIS( [MarshalAs(UnmanagedType.IUnknown)] Object punkObj, Int32 fSetFocus); + } + + public struct POINT + { + public Int32 x; + public Int32 y; + } + + public struct MSG + { + public IntPtr hwnd; + public UInt32 message; + public UInt32 wParam; + public Int32 lParam; + public UInt32 time; + public POINT pt; + } + +} \ No newline at end of file diff --git a/Deskband/BandObjectBase/RegisterLib/RegisterLib.vcproj b/Deskband/BandObjectBase/RegisterLib/RegisterLib.vcproj new file mode 100644 index 0000000..f1975df --- /dev/null +++ b/Deskband/BandObjectBase/RegisterLib/RegisterLib.vcproj @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Deskband/DeskBand/AssemblyInfo.cs b/Deskband/DeskBand/AssemblyInfo.cs new file mode 100644 index 0000000..4c31478 --- /dev/null +++ b/Deskband/DeskBand/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.0.0")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile(@"..\..\..\BandObjects.snk")] +//[assembly: AssemblyKeyName("")] diff --git a/Deskband/DeskBand/DeskBand.cs b/Deskband/DeskBand/DeskBand.cs new file mode 100644 index 0000000..5feca0f --- /dev/null +++ b/Deskband/DeskBand/DeskBand.cs @@ -0,0 +1,503 @@ +using System; +using System.ComponentModel; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Reflection; + +using Foo.Platform; +using Foo.Deskband.BandObject; +using Foo.ClientServices.GUIWPForms; +using Microsoft.Win32; + +namespace Foo.Deskband.Deskband +{ + [Guid("AE07101B-46D4-4a98-AF68-0333EA26E113")] + [BandObject("Ooganizer", BandObjectStyle.Horizontal | BandObjectStyle.TaskbarToolBar, HelpText = "Tame the Chaos : Ooganizer")] + public class DeskBand : BandObjectBase + { + private Button btnLaunch; + private IContainer components; + private System.Threading.TimerCallback _clickTimerCallback; + private System.Threading.Timer _clickTimer; + private int _previousClick = 0; + private ContextMenuStrip contextMenuStrip; + private ToolStripMenuItem settingsToolStripMenuItem; + private ToolStripMenuItem aboutToolStripMenuItem; + private ToolStripMenuItem helpToolStripMenuItem; + private ToolStripMenuItem hideToolStripMenuItem; + private ToolStripMenuItem unloadToolStripMenuItem; + private ToolStripMenuItem showToolStripMenuItem; + private ToolStripSeparator toolStripWorkspaceOptionSeparator; + private MouseButtons _previousClickMouseButton = MouseButtons.None; + + // GUI Access Object + GUIWPForms GetGUI{ get { return new GUIWPForms(); } } + + + public DeskBand() + { + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(OnAssemblyResolve); + InitializeComponent(); + InitializeClickTimer(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + components.Dispose(); + } + base.Dispose(disposing); + } + + private void InitializeClickTimer() + { + _clickTimerCallback = new System.Threading.TimerCallback(SingleClickCallback); + } + + #region Component Designer generated code + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.btnLaunch = new System.Windows.Forms.Button(); + this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); + this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.unloadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripWorkspaceOptionSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.contextMenuStrip.SuspendLayout(); + this.SuspendLayout(); + // + // btnLaunch + // + this.btnLaunch.BackColor = System.Drawing.SystemColors.ControlText; + this.btnLaunch.ContextMenuStrip = this.contextMenuStrip; + this.btnLaunch.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.btnLaunch.Font = new System.Drawing.Font("Forte", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btnLaunch.ForeColor = System.Drawing.SystemColors.ControlText; + this.btnLaunch.Location = new System.Drawing.Point(0, 0); + this.btnLaunch.Margin = new System.Windows.Forms.Padding(0); + this.btnLaunch.Name = "btnLaunch"; + this.btnLaunch.Size = new System.Drawing.Size(24, 24); + this.btnLaunch.TabIndex = 0; + this.btnLaunch.TabStop = false; + this.btnLaunch.Text = "O"; + this.btnLaunch.UseVisualStyleBackColor = false; + this.btnLaunch.HandleCreated += new System.EventHandler(this.btnLaunch_HandleCreated); + this.btnLaunch.HandleDestroyed += new System.EventHandler(this.btnLaunch_HandleDestroyed); + this.btnLaunch.Click += new System.EventHandler(this.btnLaunch_Click); + this.btnLaunch.MouseClick += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseClick); + this.btnLaunch.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseDown); + this.btnLaunch.MouseUp += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseUp); + // + // contextMenuStrip + // + this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.hideToolStripMenuItem, + this.unloadToolStripMenuItem, + this.showToolStripMenuItem, + this.toolStripWorkspaceOptionSeparator, + this.settingsToolStripMenuItem, + this.helpToolStripMenuItem, + this.aboutToolStripMenuItem}); + this.contextMenuStrip.Name = "contextMenuStrip"; + this.contextMenuStrip.Size = new System.Drawing.Size(153, 164); + this.contextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_Opening); + // + // settingsToolStripMenuItem + // + this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.settingsToolStripMenuItem.Text = "Settings"; + this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click); + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.aboutToolStripMenuItem.Text = "About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.helpToolStripMenuItem.Text = "Help"; + // + // unloadToolStripMenuItem + // + this.unloadToolStripMenuItem.Name = "unloadToolStripMenuItem"; + this.unloadToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.unloadToolStripMenuItem.Text = "Unload"; + this.unloadToolStripMenuItem.Click += new System.EventHandler(this.unloadToolStripMenuItem_Click); + // + // hideToolStripMenuItem + // + this.hideToolStripMenuItem.Name = "hideToolStripMenuItem"; + this.hideToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.hideToolStripMenuItem.Text = "Hide"; + this.hideToolStripMenuItem.Click += new System.EventHandler(this.hideToolStripMenuItem_Click); + // + // showToolStripMenuItem + // + this.showToolStripMenuItem.Name = "showToolStripMenuItem"; + this.showToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.showToolStripMenuItem.Text = "Show"; + this.showToolStripMenuItem.Click += new System.EventHandler(this.showToolStripMenuItem_Click); + // + // toolStripWorkspaceOptionSeparator + // + this.toolStripWorkspaceOptionSeparator.Name = "toolStripWorkspaceOptionSeparator"; + this.toolStripWorkspaceOptionSeparator.Size = new System.Drawing.Size(149, 6); + // + // DeskBand + // + this.BackColor = System.Drawing.SystemColors.ControlText; + this.Controls.Add(this.btnLaunch); + this.ForeColor = System.Drawing.SystemColors.ControlText; + this.MaxSize = new System.Drawing.Size(24, 24); + this.MinSize = new System.Drawing.Size(24, 24); + this.Name = "DeskBand"; + this.Title = ""; + this.contextMenuStrip.ResumeLayout(false); + this.ResumeLayout(false); + + } + #endregion + + #region Other Handlers + + private void btnLaunch_HandleCreated(object sender, EventArgs e) + { + //m_gui = new GUIWPForms(); + //MessageBox.Show("btnLaunch_Created is called!"); + } + + private void btnLaunch_HandleDestroyed(object sender, EventArgs e) + { + //m_gui = null; + //MessageBox.Show("btnLaunch_Destroyed is called!"); + } + + #endregion + + #region Button Click Handlers + + private void btnLaunch_MouseClick(object sender, MouseEventArgs e) + { + + } + + private void SingleClickCallback(Object arg) + { + switch (((MouseEventArgs)arg).Button) + { + case MouseButtons.Left: + { + //MessageBox.Show("Left Click"); + + try + { + GetGUI.LaunchArtifactWall(this.Handle); + } + catch (Exception e) + { + MessageBox.Show(e.Message); + } + + //LaunchArtifactWall(); + + break; + } + case MouseButtons.Right: + { + //LaunchContextMenu((MouseEventArgs)arg); + + break; + } + case MouseButtons.Middle: + { + // TODO - Handle middle button ... if desired + + break; + } + default: + { + break; + } + } + } + + private void DoubleClickCallback(MouseEventArgs args) + { + switch (args.Button) + { + case MouseButtons.Left: + { + try + { + GetGUI.LaunchWorkspaceSelector(this.Handle); + } + catch (Exception e) + { + MessageBox.Show(e.Message); + } + + //LaunchWorkspaceSelector(); + + break; + } + case MouseButtons.Right: + { + // TODO - Handle right button double click ... if desired + + break; + } + case MouseButtons.Middle: + { + // TODO - Handle middle button double click ... if desired + + break; + } + default: + { + break; + } + } + } + + private void LaunchContextMenu(MouseEventArgs args) + { + contextMenuStrip.Show(PointToScreen(args.Location)); + } + + private void btnLaunch_Click(object sender, EventArgs e) + { + + } + + private void btnLaunch_MouseDown(object sender, MouseEventArgs e) + { + // Do not remove this handler ... it seems to quiet down the taskbar context menu + // so we can do our own context menu + } + + private void btnLaunch_MouseUp(object sender, MouseEventArgs e) + { + int now = System.Environment.TickCount; + + if ((now - _previousClick) <= SystemInformation.DoubleClickTime && + e.Button == _previousClickMouseButton) + { + // Cancel click timer ... we've got a double click instead + _clickTimer.Change(System.Threading.Timeout.Infinite, + System.Threading.Timeout.Infinite); + + DoubleClickCallback(e); + + _previousClick = 0; + } + else + { + _previousClick = now; + _previousClickMouseButton = e.Button; + + // Fire the OnClick event after the DoubleClickTime so that double-click handling gets a chance + _clickTimer = new System.Threading.Timer(_clickTimerCallback, + (Object)e, + (int)(SystemInformation.DoubleClickTime * 1.3), + System.Threading.Timeout.Infinite); + } + } + + #endregion + + /// + /// Assembly Resolve Handler for entire Component + /// + static System.Reflection.Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + { + + string installPath = ""; + RegistryKey RootKey = Registry.LocalMachine.OpenSubKey("Software\\Ooganizer", false); + if (RootKey != null) + { + object keyvalue = RootKey.GetValue("InstallPath");; + if ((keyvalue != null) && (keyvalue.ToString() != "")) + installPath = keyvalue.ToString(); + } + + string[] asmName = args.Name.Split(','); + switch (asmName[0]) + { + case "GUIWPForms": + return Assembly.LoadFile(installPath + @"GUIWPForms.dll", Assembly.GetExecutingAssembly().Evidence); + + case "Platform": + return Assembly.LoadFile(installPath + @"Platform.dll", Assembly.GetExecutingAssembly().Evidence); + + default: + return null; + } + + //Assembly assembly = null; + //string[] asmName = args.Name.Split(','); + //string basePath = ""; + + //RegistryKey RootKey = Registry.LocalMachine.OpenSubKey("Software\\Ooganizer", false); + //if (RootKey != null) + //{ + // object keyvalue = null; + // keyvalue = RootKey.GetValue("InstallPath"); + // if ((keyvalue != null) && (keyvalue.ToString() != "")) + // basePath = keyvalue.ToString(); + //} + + //MessageBox.Show(System.Environment.CurrentDirectory); + ////MessageBox.Show(asmName[0]); + //switch (asmName[0]) + //{ + // case "GUIWPForms": + // assembly = Assembly.LoadFile(basePath + @"GUIWPForms.dll", Assembly.GetExecutingAssembly().Evidence); + // break; + // case "Platform": + // assembly = Assembly.LoadFile(basePath + @"Platform.dll", Assembly.GetExecutingAssembly().Evidence); + // break; + // default: + // break; + //} + + //return assembly; + } + + #region ContextMenu Handlers + + private void contextMenuStrip_Opening(object sender, CancelEventArgs e) + { + //string currentWorkspace = null; + //OoganizerState.WorkspaceState workspaceState = OoganizerState.WorkspaceState.Unloaded; + + //using (OoganizerState oogyState = new OoganizerState()) + //{ + // currentWorkspace = oogyState.GetCurrentWorkspace(); + + // if (currentWorkspace != null) + // { + // workspaceState = oogyState.GetWorkspaceState(currentWorkspace); + // } + //} + + //if (currentWorkspace == null) + //{ + // // Hide these options when there is no workspace loaded + // this.hideToolStripMenuItem.Visible = false; + // this.unloadToolStripMenuItem.Visible = false; + // this.showToolStripMenuItem.Visible = false; + // this.toolStripWorkspaceOptionSeparator.Visible = false; + //} + //else + //{ + // switch (workspaceState) + // { + // case OoganizerState.WorkspaceState.Hidden: + // this.hideToolStripMenuItem.Visible = false; + // this.unloadToolStripMenuItem.Visible = true; + // this.showToolStripMenuItem.Visible = true; + // this.toolStripWorkspaceOptionSeparator.Visible = true; + + // break; + + // case OoganizerState.WorkspaceState.Shown: + // this.hideToolStripMenuItem.Visible = true; + // this.unloadToolStripMenuItem.Visible = true; + // this.showToolStripMenuItem.Visible = false; + // this.toolStripWorkspaceOptionSeparator.Visible = true; + + // break; + + // default: + // // Otherwise hide workspace options + // this.hideToolStripMenuItem.Visible = false; + // this.unloadToolStripMenuItem.Visible = false; + // this.showToolStripMenuItem.Visible = false; + // this.toolStripWorkspaceOptionSeparator.Visible = false; + + // break; + // } + //} + } + + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + // Display About Form ... Form should provide : + // * company and product version information + // * support website / phone number + MessageBox.Show("Ooganizer 1.0"); + } + + private void settingsToolStripMenuItem_Click(object sender, EventArgs e) + { + // Display Settings Form ... Form should provide : + // * Settings + MessageBox.Show("Ooganizer Settings Form"); + } + + private void hideToolStripMenuItem_Click(object sender, EventArgs e) + { + //string currWorkspaceName = null; + + //using (OoganizerState oogyState = new OoganizerState()) + //{ + // currWorkspaceName = oogyState.GetCurrentWorkspace(); + + // if (currWorkspaceName != null) + // { + // oogyState.HideWorkspace(currWorkspaceName); + // } + //} + } + + private void showToolStripMenuItem_Click(object sender, EventArgs e) + { + //string currWorkspaceName = null; + + //using (OoganizerState oogyState = new OoganizerState()) + //{ + // currWorkspaceName = oogyState.GetCurrentWorkspace(); + + // if (currWorkspaceName != null) + // { + // oogyState.ShowWorkspace(currWorkspaceName); + // } + //} + } + + private void unloadToolStripMenuItem_Click(object sender, EventArgs e) + { + //string currWorkspaceName = null; + + //using (OoganizerState oogyState = new OoganizerState()) + //{ + // currWorkspaceName = oogyState.GetCurrentWorkspace(); + + // if (currWorkspaceName != null) + // { + // string currentWorkspaceName = oogyState.GetCurrentWorkspace(); + + // if (currentWorkspaceName != null) + // { + // oogyState.UnloadWorkspace(currentWorkspaceName); + // } + // } + //} + } + + #endregion + + + } +} diff --git a/Deskband/DeskBand/DeskBand.csproj b/Deskband/DeskBand/DeskBand.csproj new file mode 100644 index 0000000..79a58a5 --- /dev/null +++ b/Deskband/DeskBand/DeskBand.csproj @@ -0,0 +1,174 @@ + + + Local + 9.0.30729 + 2.0 + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7} + Debug + AnyCPU + + + + + Foo.DeskBand + MyKeyFile.SNK + JScript + Grid + IE50 + false + Library + Foo.Deskband.Deskband + + + + + 0.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + true + + + + + + + + + v3.5 + + + ..\..\Target\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + false + false + false + 4 + full + prompt + + + ..\..\Target\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + true + false + false + false + 4 + none + prompt + + + + System + + + System.Data + + + System.Drawing + + + + System.Windows.Forms + + + System.XML + + + + + Code + + + UserControl + + + True + True + Resources.resx + + + DeskBand.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + + + {A02E052C-3C52-43DB-BB30-A47446B8165F} + GUIWPForms + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} + BandObject + + + + + "$(FrameworkSDKDir)bin\gacutil.exe" /uf "$(TargetName)" + "$(FrameworkSDKDir)bin\gacutil.exe" /if "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" +"$(FrameworkDir)\regasm.exe" "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" tlb:$(TargetName).tlb /codebase + + \ No newline at end of file diff --git a/Deskband/DeskBand/DeskBand.resx b/Deskband/DeskBand/DeskBand.resx new file mode 100644 index 0000000..bd3ae11 --- /dev/null +++ b/Deskband/DeskBand/DeskBand.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Deskband/DeskBand/DeskBand.sln b/Deskband/DeskBand/DeskBand.sln new file mode 100644 index 0000000..bc198aa --- /dev/null +++ b/Deskband/DeskBand/DeskBand.sln @@ -0,0 +1,91 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeskBand", "DeskBand.csproj", "{ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}" + ProjectSection(ProjectDependencies) = postProject + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} = {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Register", "Register\Register.vcproj", "{E35915FE-ED91-4AE5-B566-F269CD854498}" + ProjectSection(ProjectDependencies) = postProject + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7} = {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BandObject", "..\BandObjectBase\BandObject.csproj", "{BDB3B670-A17B-483E-954C-52FC2B6FF9D3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegisterLib", "..\BandObjectBase\RegisterLib\RegisterLib.vcproj", "{A6903D99-B950-4D1A-B715-0B808ED64376}" + ProjectSection(ProjectDependencies) = postProject + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} = {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} + EndProjectSection +EndProject +Global + GlobalSection(TeamFoundationVersionControl) = preSolution + SccNumberOfProjects = 5 + SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} + SccTeamFoundationServer = http://myhome.romischer.com:8080/ + SccLocalPath0 = . + SccProjectUniqueName1 = Register\\Register.vcproj + SccProjectName1 = Register + SccLocalPath1 = Register + SccProjectUniqueName2 = DeskBand.csproj + SccLocalPath2 = . + SccProjectUniqueName3 = ..\\BandObjectBase\\BandObject.csproj + SccProjectName3 = ../BandObjectBase + SccLocalPath3 = ..\\BandObjectBase + SccProjectUniqueName4 = ..\\BandObjectBase\\RegisterLib\\RegisterLib.vcproj + SccProjectName4 = ../BandObjectBase/RegisterLib + SccLocalPath4 = ..\\BandObjectBase\\RegisterLib + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Win32.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Any CPU.Build.0 = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Win32.ActiveCfg = Release|Any CPU + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Win32.ActiveCfg = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Debug|Win32.Build.0 = Debug|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Any CPU.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Mixed Platforms.Build.0 = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Win32.ActiveCfg = Release|Win32 + {E35915FE-ED91-4AE5-B566-F269CD854498}.Release|Win32.Build.0 = Release|Win32 + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Win32.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Win32.ActiveCfg = Release|Any CPU + {A6903D99-B950-4D1A-B715-0B808ED64376}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Debug|Win32.ActiveCfg = Debug|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Debug|Win32.Build.0 = Debug|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Release|Any CPU.ActiveCfg = Release|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Release|Mixed Platforms.Build.0 = Release|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Release|Win32.ActiveCfg = Release|Win32 + {A6903D99-B950-4D1A-B715-0B808ED64376}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Deskband/DeskBand/MyKeyFile.SNK b/Deskband/DeskBand/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Deskband/DeskBand/MyKeyFile.SNK differ diff --git a/Deskband/DeskBand/Properties/Resources.Designer.cs b/Deskband/DeskBand/Properties/Resources.Designer.cs new file mode 100644 index 0000000..855091e --- /dev/null +++ b/Deskband/DeskBand/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Deskband.Deskband.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.Deskband.Deskband.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Deskband/DeskBand/Properties/Resources.resx b/Deskband/DeskBand/Properties/Resources.resx new file mode 100644 index 0000000..5ea0895 --- /dev/null +++ b/Deskband/DeskBand/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Deskband/DeskBand/Register/Register.vcproj b/Deskband/DeskBand/Register/Register.vcproj new file mode 100644 index 0000000..7a738d0 --- /dev/null +++ b/Deskband/DeskBand/Register/Register.vcproj @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GUILib/GUICommon.cs b/GUILib/GUICommon.cs new file mode 100644 index 0000000..0e975d4 --- /dev/null +++ b/GUILib/GUICommon.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; +using System.Diagnostics; + +// Ooganizer Namespaces +using Foo.Platform; +using Foo.Platform.Interacters; +using Foo.Platform.Win32; + +namespace Foo.GUILib +{ + /// + /// This is the generic GUICommon Class, that serves us a generic implementation to + /// everyone as to isolate ourselves from OS Changes + /// + public class GUICommon + { + // Keep track of all the origianl window positions that go + // thru here, ~we delete them when position back to org position + // get's called. + private static Dictionary s_orgWindowPosMap; + private static bool s_bOutOfProc_UseBH = false; + + // public properties + public static bool OutOfProc { get { return s_bOutOfProc_UseBH; } } + + // keep track of Window Positions + static GUICommon() + { + s_orgWindowPosMap = new Dictionary(); + } + + /// + /// Performs a screen snapshot of the passed in window handle. + /// + /// Window to Snap + /// a window image + public static Image PerformSnapshot(IntPtr hWnd) + { + if (hWnd != IntPtr.Zero) + { + ScreenCapture screencap = new ScreenCapture(); + + if (Env.Theme == Env.Themes.AeroTheme) + return screencap.SaveWindowUsingFullScreenShotCrop(hWnd); + else + return screencap.SaveWindowUsingDCNBitBlt(hWnd, false); + } + return null; + } + + /// + /// Positions a window in the center at Golden Ratio and takes a snapshot. + /// ~corner stone of our add workspace strategy + /// + /// handle to the window to manipulate + /// Set to true to use ButtonHook to Perform the action + public static Image PositionWindowToGoldenPosAndTakeSnapshot(IntPtr hWnd, bool bOutOfProc) + { + // use ButtonHook, Yes / No? + s_bOutOfProc_UseBH = bOutOfProc; + + // First thing to do is to save the org position + RECT rect; + Win32Functions.GetWindowRect(hWnd, out rect); + s_orgWindowPosMap[hWnd] = rect; + + // First we fade the window totally away + FadeWindow(hWnd, true); + + // now we want to fade it out of the monitor center + // However using the golden ratio as the size + FadeWindowOutOfMonitorCenterInGoldenRatio(hWnd, rect); + + // Make sure we are in position and drawing at this point, + // perform the snapshot and return + System.Threading.Thread.Sleep(10); + + //PositionWindowBackToWhereItWas(hWnd); + + Image image = PerformSnapshot(hWnd); + //image.Save(@"D:\Users\HPInvent\Desktop\Snapshot1.png", System.Drawing.Imaging.ImageFormat.Png); + //return null; + + return image; + } + + /// + /// Positions a window back to where it was prior to calling PositionWindowToGoldenPosAndTakeSnapshot(). + /// ~Hence, you should call this after calling that function + /// + /// handle to the window to manipulate + /// Set to true to use ButtonHook to Perform the action + public static void PositionWindowBackToWhereItWas(IntPtr hWnd, bool bOutOfProc) + { + // use ButtonHook, Yes / No? + s_bOutOfProc_UseBH = bOutOfProc; + + // try to retrieve the org value from the map + if (!s_orgWindowPosMap.ContainsKey(hWnd)) + return; + + RECT orgRect = s_orgWindowPosMap[hWnd]; + + // Set the Window totally invisible + SetAlphaTransparency(hWnd, 0); + + // As part of the effect, wait a little + System.Threading.Thread.Sleep(60); + + // Now just flat out position it back to where it was + Win32Functions.SetWindowPos(hWnd, IntPtr.Zero, orgRect.left, orgRect.top, orgRect.AsRectangle.Width, orgRect.AsRectangle.Height, (uint)SetWindowPosFlags.SWP_SHOWWINDOW); + + // Now Fade the Window out + FadeWindow(hWnd, false); + + //SetAlphaTransparency(hWnd, 0); // invisible + //SetAlphaTransparency(hWnd, 255); // visible + + // since we positioned the window back to where it was, + // we no longer need to keep track of it's org position + s_orgWindowPosMap.Remove(hWnd); + } + + /// + /// Use this generic function to set the transparency + /// + private static void SetAlphaTransparency(IntPtr hWnd, byte alpha) + { + if (s_bOutOfProc_UseBH) + BHInteracter.SetWindowTransparency(hWnd, alpha); + else + Win32_WrapperFunc.SetAlphaChannel(hWnd, alpha); + } + + /// + /// The Golden Ratio (~1.618) is used for the Snapshot to give it the best look + /// + /// pass in th screen for which to calculate the ratio for + /// the width and height to achieve the best golden ratio for that screen + private static void CalculateGoldenRatio(Screen screen, out RECT rect) + { + const int _MAXHEIGHT = 1100; // max pleasing height + const double _fGoldenRatio = 1.618; + const double _fsafetybuffer = 10; // 10% just in case + // safety buffer for height/width + + int maxHeight = screen.WorkingArea.Height; + int maxWidth = screen.WorkingArea.Width; + + // is this a potrait screen? + bool bIsPortrait = maxHeight > maxWidth; + + // calculated height and width + int height = 0; + int width = 0; + + // Normal Screen + if (!bIsPortrait) + { + // calculated height and width; + height = maxHeight - (int)(((double)maxHeight / 100) * _fsafetybuffer); + width = (int)((double)height / _fGoldenRatio); + } + else // Portrait + { + width = maxWidth - (int)(((double)maxWidth / 100) * _fsafetybuffer); + height = (int)((double)width * _fGoldenRatio); + } + + // Enforce that the height is not bigger than _MAXHEIGHT, anything bigger than + // that just look unpleasant. + if (height >= _MAXHEIGHT) + { + height = _MAXHEIGHT; + width = (int)((double)height / _fGoldenRatio); + } + + // pass out the calculated height and width + rect.left = 0; + rect.top = 0; + rect.bottom = height; + rect.right = width; + } + + /// + /// Use this to quickle fade a window + /// + /// Set to true to fade in, false to Fade out + private static void FadeWindow(IntPtr hWnd, bool bFadeIn) + { + + // Stole Increment Fading from Buttonhook + const int LOWER_INCREMENT = 7; + const int MIDDLE_INCREMENT = 15; + const int UPPER_INCREMENT = 25; + + // Increment Points *inverted* + const int LOWER_POINT = 60; + const int MIDDLE_POINT = 160; + const int UPPER_POINT = 230; + + // Fade in or Fade out? + byte alpha = (!bFadeIn)? (byte)0 : (byte)255; + bool bDone = false; + + if (!bFadeIn) // FadeOut + { + while (!bDone) + { + if (alpha >= UPPER_POINT) + { + alpha = 255; // just show the thing already + bDone = true; + } + else if (alpha <= LOWER_POINT) + alpha += LOWER_INCREMENT; + else if (alpha <= MIDDLE_POINT) + alpha += MIDDLE_INCREMENT; + else + alpha += UPPER_INCREMENT; + + SetAlphaTransparency(hWnd, alpha); + System.Threading.Thread.Sleep(20); + } + } + else // FadeIn + { + while (!bDone) + { + if (alpha <= (255 - UPPER_POINT)) //25 + { + alpha = 0; // just hide the thing already + bDone = true; + } + else if (alpha >= (255 - LOWER_POINT)) //195 + alpha -= LOWER_INCREMENT; + else if (alpha >= (255 - MIDDLE_POINT)) // 95 + alpha -= MIDDLE_INCREMENT; + else + alpha -= UPPER_INCREMENT; + + SetAlphaTransparency(hWnd, alpha); + System.Threading.Thread.Sleep(20); + } + } + } + + /// + /// Helper function to determine the monitor and it's center and + /// fade out the window there in GoldenRatio Siz + /// + private static void FadeWindowOutOfMonitorCenterInGoldenRatio(IntPtr hWnd, RECT orgRect) + { + // get the screen the original rect was mostly located + Screen screen = Screen.FromRectangle(orgRect.AsRectangle); + + // now figure out the best rect to use for this screen + RECT goldenRect; + CalculateGoldenRatio(screen, out goldenRect); + + // calculate where we must place the golden window + // (centering it on the screen) + Point pt = new Point(); + pt.Y = (screen.Bounds.Height - goldenRect.AsRectangle.Height) / 2; + pt.X = (screen.Bounds.Width - goldenRect.AsRectangle.Width) / 2; + + // Calculate the window center according to the screen + pt.Y = screen.Bounds.Top + pt.Y; + pt.X = screen.Bounds.Left + pt.X; + + // Make the window totally transparent and show it in the golden ratio position + SetAlphaTransparency(hWnd, 0); + Win32Functions.SetWindowPos(hWnd, IntPtr.Zero, pt.X, pt.Y, goldenRect.AsRectangle.Width, goldenRect.AsRectangle.Height, (uint) SetWindowPosFlags.SWP_SHOWWINDOW); + + // Now Fade the Window out + FadeWindow(hWnd, false); + } + + } +} + diff --git a/GUILib/GUILib.csproj b/GUILib/GUILib.csproj new file mode 100644 index 0000000..48fbdd5 --- /dev/null +++ b/GUILib/GUILib.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {C1282050-455B-44F4-8520-1C005E38EFB2} + Library + Properties + Foo.GUILib + GUILib + v3.5 + 512 + + + + + + + + + + + true + MyKeyFile.SNK + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + False + ..\Components\log4net.dll + + + 3.0 + + + 3.0 + + + + 3.5 + + + + 3.5 + + + + + + 3.0 + + + 3.0 + + + + + + + + + + + + + + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + + + + + + + \ No newline at end of file diff --git a/GUILib/MyKeyFile.SNK b/GUILib/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/GUILib/MyKeyFile.SNK differ diff --git a/GUILib/Properties/AssemblyInfo.cs b/GUILib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0053aea --- /dev/null +++ b/GUILib/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GUILib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GUILib")] +[assembly: AssemblyCopyright("Copyright © 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("451a4209-15d4-49ef-a70f-2cc6c6d524b5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/GUILib/ScreenCapture.cs b/GUILib/ScreenCapture.cs new file mode 100644 index 0000000..92d4734 --- /dev/null +++ b/GUILib/ScreenCapture.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; + +using Foo.Platform; +using Foo.Platform.Win32; + +namespace Foo.GUILib +{ + + public class ScreenCapture + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Saves a Window using a DC of the Full Screen, then crops the window out of the + /// full screen capture. We have to do this because SaveWindowUsingDCNBitBlt() doesn't + /// work for all programs that overwrite the glass area on Aero (like MS Office) + /// + /// + /// IMP! - This function will work on some multiple monitor configurations but currently NOT all! + /// If for example, the primary display is on the left and sec on the right, and the window is on the + /// right monitor, then all x and y values will be positive, (We currently only handle multiple monitors, + /// where one x or y value is negative!), + /// ~more calculations must be done for multiple x, multiple y positive configurations + /// + /// handle to a Window + public Image SaveWindowUsingFullScreenShotCrop(IntPtr hWnd) + { + try + { + // First get the Window Rect + RECT rectWnd; + Win32Functions.GetWindowRect(hWnd, out rectWnd); + + // Now figure out which monitor the window is in + IntPtr hMonitor = Win32Functions.MonitorFromRect(ref rectWnd, (int)Win32_Constants.MONITOR_DEFAULTTONEAREST); + + // Get the szDevice Name for the Monitor + MONITORINFOEX monitorinfoex = new MONITORINFOEX(); + monitorinfoex.cbSize = Marshal.SizeOf(monitorinfoex); + if (!Win32Functions.GetMonitorInfo(hMonitor, ref monitorinfoex)) + return null; + + // Use szDevice to create a DC + IntPtr hDC = Win32Functions.CreateDC(monitorinfoex.szDeviceName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + + //Here we make a compatible device context in memory for screen device context. + IntPtr hMemDC = Win32Functions.CreateCompatibleDC(hDC); + + // Let's get all the monitor dimensions we need + Rectangle rectDim = monitorinfoex.rcMonitor.AsRectangle; + int DisplayHeight = rectDim.Height; + int DisplayWidth = rectDim.Width; + + //The .net way to retrieve dimensions + Screen screen = Screen.FromHandle(hWnd); + + //We create a compatible bitmap of screen size using screen device context. + IntPtr hBitmap = Win32Functions.CreateCompatibleBitmap(hDC, DisplayWidth, DisplayHeight); + + if (hBitmap != IntPtr.Zero) + { + //Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap. + IntPtr hOld = (IntPtr)Win32Functions.SelectObject(hMemDC, hBitmap); + + //We copy the Bitmap to the memory device context. + Win32Functions.BitBlt(hMemDC, 0, 0, DisplayWidth, DisplayHeight, hDC, 0, 0, Win32_Constants.SRCCOPY); + + //We select the old bitmap back to the memory device context. + Win32Functions.SelectObject(hMemDC, hOld); + + //We delete the memory device context. + Win32Functions.DeleteDC(hMemDC); + + //Delete the screen device context. + Win32Functions.DeleteDC(hDC); + + //Image is created by Image bitmap handle and stored in local variable. + Image image = (Image)System.Drawing.Image.FromHbitmap(hBitmap); + + // * For Debugging * + //string strFileNameNPathWExtPNG = (Env.GetSnapshotDirectory() + @"\" + hWnd.ToString() + ".png"); + //image.Save(strFileNameNPathWExtPNG, System.Drawing.Imaging.ImageFormat.Png); + + //Release the memory for compatible bitmap. + Win32Functions.DeleteObject(hBitmap); + + //// + // Imp! - Now we want to crop the Window out of the Screen Image + // NOTE! - Here we convert the screen positions into the corresponding + // image position on that screen + //// + int height = rectWnd.AsRectangle.Height; + int width = rectWnd.AsRectangle.Width; + + rectWnd.left = Math.Abs(rectWnd.left - screen.Bounds.Left); + rectWnd.right = rectWnd.left + width; + + rectWnd.top = Math.Abs(rectWnd.top - screen.Bounds.Top); + rectWnd.bottom = rectWnd.top + height; + + // Convert the Rectangle for .Net Use + Rectangle rectangleWnd = rectWnd.AsRectangle; + + Bitmap bmpImage = new Bitmap(image); + Bitmap bmpCrop = bmpImage.Clone(rectangleWnd, bmpImage.PixelFormat); + + //Bitmap bmpCrop = (Bitmap)image; + //bmpCrop = bmpCrop.Clone(rectangleWnd, bmpCrop.PixelFormat); + + return (Image)bmpCrop; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error thrown", MethodBase.GetCurrentMethod().Name), e); + } + + return null; + } + + /// + /// Saves the Window using a DC, this works well for bUseClientDC = true, but doesn't + /// work when using the Window's DC because of Aero drawing via directx, the window frame + /// won't be in the image + /// + /// handle to a Window + /// true to use ClientDC, false to use WindowDC + public Image SaveWindowUsingDCNBitBlt(IntPtr hWnd, bool bUseClientDC) + { + try + { + SIZE size; + IntPtr hDC; + IntPtr hBitmap; + Image image; + RECT Rect = new RECT(); + + if (bUseClientDC) + Win32Functions.GetClientRect(hWnd, out Rect); + else + Win32Functions.GetWindowRect(hWnd, out Rect); + + size.cx = (Rect.right - Rect.left); + size.cy = (Rect.bottom - Rect.top); + + // TRY USING GetDCEx() - May actually do better + //hDC = Win32Functions.GetDCEx(hWnd); + if (bUseClientDC) + hDC = Win32Functions.GetDC(hWnd); + else + hDC = Win32Functions.GetWindowDC(hWnd); + + //Here we make a compatible device context in memory for screen device context. + IntPtr hMemDC = Win32Functions.CreateCompatibleDC(hDC); + + //We create a compatible bitmap of screen size using screen device context. + hBitmap = Win32Functions.CreateCompatibleBitmap(hDC, size.cx, size.cy); + + if (hBitmap != IntPtr.Zero) + { + //Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap. + IntPtr hOld = (IntPtr)Win32Functions.SelectObject(hMemDC, hBitmap); + + //We copy the Bitmap to the memory device context. + Win32Functions.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, Win32_Constants.SRCCOPY); + + //We select the old bitmap back to the memory device context. + Win32Functions.SelectObject(hMemDC, hOld); + + //We delete the memory device context. + Win32Functions.DeleteDC(hMemDC); + + //We release the screen device context. + Win32Functions.ReleaseDC(hWnd, hDC); + + //Image is created by Image bitmap handle and stored in local variable. + image = (Image)System.Drawing.Image.FromHbitmap(hBitmap); + + // * For Debugging * + //string strFileNameNPathWExtPNG = (Env.GetSnapshotDirectory() + @"\" + hWnd.ToString() + ".png"); + //image.Save(strFileNameNPathWExtPNG, System.Drawing.Imaging.ImageFormat.Png); + + //Release the memory for compatible bitmap. + Win32Functions.DeleteObject(hBitmap); + return image; + } + else + { + Log.Error(string.Format("{0}() - hBitmap is Null, something is wrong", MethodBase.GetCurrentMethod().Name)); + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error thrown", MethodBase.GetCurrentMethod().Name), e); + } + + return null; + } + } +} diff --git a/GUILib/WPFHelper.cs b/GUILib/WPFHelper.cs new file mode 100644 index 0000000..c5d660c --- /dev/null +++ b/GUILib/WPFHelper.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows.Media.Imaging; +using System.Windows.Media; +using System.Windows; + +namespace Foo.GUILib +{ + static public class WPFHelper + { + /// + /// Useful to create a simple wrapping tooltip for a wpf control + /// + /// + /// Set to 0 to leave default, else set to 0> to define max height + /// Set to 0 to leave default, else set to 0> to define max width + /// a ToolTip Object to assign to a control + public static ToolTip CreateNewStringToolTip(string strToolTipContent, int height, int width) + { + // Create the TextBlock + TextBlock tx = new TextBlock(); + if(height > 0) + tx.Height = height; + if(width > 0) + tx.Width = width; + tx.TextWrapping = TextWrapping.Wrap; + tx.Text = strToolTipContent; + + // Create the ToolTip with the TextBlock inside + ToolTip tt = new ToolTip(); + tt.Content = strToolTipContent; + return tt; + } + + /// + /// Useful if you want to know if the Mouse cursor is over the specified Wpf Window + /// (Uses windowsforms to do the calculations) + /// + /// true if the mouse cursor is over the specified form window, false otherwise + public static bool IsMouseCursorOverWPFormWindow(Window wpfWindow) + { + if (wpfWindow != null) + { + // Get the Point location of the mouse cursor + System.Drawing.Point point = System.Windows.Forms.Cursor.Position; + + // Get the rect for the Navigation Form + Point wpfFormLeftTopPoint = new Point(wpfWindow.Left, wpfWindow.Top); + Size wpfFormSize = new Size(wpfWindow.Width, wpfWindow.Height); + Rect rect = new Rect(wpfFormLeftTopPoint, wpfFormSize); + + // Return if the Mouse is over the Navigation Form + return (rect.Contains((double)point.X, (double)point.Y)); + } + return false; + } + + /// + /// For Dynamically Creating Text ComboBox Items + /// + /// Text Content to Display + /// object to tag to the menu item + /// + public static ComboBoxItem CreateAComboBoxItem(string strContent, object tag) + { + if (!String.IsNullOrEmpty(strContent) && (tag != null)) + { + ComboBoxItem item = new ComboBoxItem(); + item.Content = strContent; + item.Tag = tag; + return item; + } + return null; + } + + /// + /// For dynamically creating Image sources, this function helps you to create an image out of + /// a Resource Uri. You can then assign this image to a 'Source' property on an image wpf object + /// + /// a valid relative Resource Uri String to an image + /// the output image's desired height + /// the output image's desired width + /// + public static Image CreateWPFImageFromRelativeResourceUri(string strRelativeResourceUri, int ImageHeight, int ImageWidth) + { + if (!String.IsNullOrEmpty(strRelativeResourceUri)) + { + Image myImage = new Image(); + BitmapImage image = new BitmapImage(); + image.BeginInit(); + image.UriSource = new Uri(strRelativeResourceUri, UriKind.Relative); + image.EndInit(); + myImage.Stretch = Stretch.Fill; + myImage.Height = ImageHeight; + myImage.Width = ImageWidth; + myImage.Source = image; + return myImage; + } + return null; + } + + } +} diff --git a/GUILib/WPFHiddenWindow.cs b/GUILib/WPFHiddenWindow.cs new file mode 100644 index 0000000..c0fd561 --- /dev/null +++ b/GUILib/WPFHiddenWindow.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows.Media.Imaging; +using System.Windows.Media; +using System.Windows; +using System.Windows.Interop; + +namespace Foo.GUILib +{ + /// + /// Class used to keep WPF Windows Hidden permanently. + /// Should be called by Performance WPF Window 'Hidden' loads + /// when constructed, and when loaded. + /// + /// Note: All WPFWindow's that use this class don't set certain properties on the + /// window until they are loaded and it's NOT a performance Cache window. + /// + public static class WPFHiddenWindow + { + private static Dictionary s_hWndToWindowMap = new Dictionary(); + + /// + /// * Core * 'Hiding' Function. Makes sure that the Window is and + /// stays hidden. + /// + /// a WPF window object + private static void HideWPFWindow(Window wpfWindow) + { + // Force Opacity + wpfWindow.WindowStyle = WindowStyle.None; + wpfWindow.Opacity = 0.0; + wpfWindow.ShowInTaskbar = false; + wpfWindow.ShowActivated = false; + + // Force a tiny Window in top-left corner + wpfWindow.Width = 5; + wpfWindow.Height = 5; + wpfWindow.Top = 0; + wpfWindow.Left = 0; + wpfWindow.WindowStartupLocation = WindowStartupLocation.Manual; + } + + /// + /// Call this to execute a Show() call on a wpfWindow Performance cache window. Returns true + /// if bPerformanceCache is true. This means that this Function did something to the window. + /// + /// a WPF window object + /// Pass in true, if this is a performance Cache window + /// true if bPerformanceCache is true, false otherwise + public static bool ExecuteShowOnAHiddenWindow(Window wpfWindow, bool bPerformanceCache) + { + if (bPerformanceCache) + { + HideWPFWindow(wpfWindow); + wpfWindow.Show(); + wpfWindow.Hide(); + return true; + } + return false; + } + + /// + /// Call this in your WPFWindow's constructor. Returns true if bPerformanceCache is true. + /// This means that this Function did something to the window. + /// + /// a WPF window object + /// Pass in true, if this is a performance Cache window + /// true if bPerformanceCache is true, false otherwise + public static bool HiddenWindowConstructor(Window wpfWindow, bool bPerformanceCache) + { + if (bPerformanceCache) + { + HideWPFWindow(wpfWindow); + return true; + } + return false; + } + + /// + /// Call this from your WPFWindow's OnLoad Event. Returns true if bPerformanceCache is true. + /// This means that this Function did something to the window. + /// + /// a WPF window object + /// Pass in true, if this is a performance Cache window + /// true if bPerformanceCache is true, false otherwise + public static bool HiddenWindowOnLoad(Window wpfWindow, bool bPerformanceCache) + { + if (bPerformanceCache) + { + HideWPFWindow(wpfWindow); + + // Add Message Hook for performanceCache WPForm * To make sure it is always invisible * + WindowInteropHelper interop = new WindowInteropHelper(wpfWindow); + HwndSource source = HwndSource.FromHwnd(interop.Handle); + source.AddHook(new HwndSourceHook(MessageHook)); + s_hWndToWindowMap[interop.Handle] = wpfWindow; + return true; + } + return false; + } + + /// + /// Call this from your WPFWindow's Closing Event. Returns true if bPerformanceCache is true. + /// This means that this Function did something to the window. + /// + /// a WPF window object + /// Pass in true, if this is a performance Cache window + /// true if bPerformanceCache is true, false otherwise + public static bool HiddenWindowClosing(Window wpfWindow, bool bPerformanceCache) + { + if (s_hWndToWindowMap.ContainsValue(wpfWindow)) + { + foreach (IntPtr hWnd in s_hWndToWindowMap.Keys) + { + if (s_hWndToWindowMap[hWnd] == wpfWindow) + { + s_hWndToWindowMap.Remove(hWnd); + break; + } + } + return true; + } + return false; + } + + /// + /// This Message Hook is for the Hidden wpfForm that we use for better performance, + /// We want to make sure that it is never displayed *It can occur that explorer.exe can show it, without this hook* + /// ~i.e. when explorer.exe crashes, and get's restarted + /// + private static IntPtr MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + // Get the Proper WPF Object and make sure it is Hidden + if (s_hWndToWindowMap.ContainsKey(hwnd)) + { + Window wpfWindow = s_hWndToWindowMap[hwnd]; + if (wpfWindow != null) + HideWPFWindow(wpfWindow); + } + + handled = false; + return System.IntPtr.Zero; + } + } +} diff --git a/GUILib/app.config b/GUILib/app.config new file mode 100644 index 0000000..b7db281 --- /dev/null +++ b/GUILib/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Hooks/ButtonHook/ButtonHook.cpp b/Hooks/ButtonHook/ButtonHook.cpp new file mode 100644 index 0000000..1396732 --- /dev/null +++ b/Hooks/ButtonHook/ButtonHook.cpp @@ -0,0 +1,1153 @@ +// This is the main DLL file. + +#include "stdafx.h" +#define DLLAPI_BUTTON_HOOK +#include "ButtonHook.h" +#include + +using namespace Ooganizer; + +#ifdef _DEBUG + #import "..\\..\\Target\\Debug\\Settings.tlb" raw_interfaces_only +#else + #import "..\\..\\Target\\Release\\Settings.tlb" raw_interfaces_only +#endif +using namespace Settings; + +#ifdef _DEBUG + #import "..\\..\\Target\\Debug\\Platform.tlb" raw_interfaces_only +#else + #import "..\\..\\Target\\Release\\Platform.tlb" raw_interfaces_only +#endif +using namespace Platform; + +#ifdef _DEBUG + #import "..\\..\\Target\\Debug\\ButtonWPForm.tlb" +#else + #import "..\\..\\Target\\Release\\ButtonWPForm.tlb" +#endif +using namespace ButtonWPForm; + +//// +// ***** What type of Windows should have the Button ***** +//// +const DWORD WS_STYLES_TO_TEST_FOR = WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU; + +//// +// ***** Top-Level Dialogs ***** +//// +const DWORD WS_STYLES_TO_TEST_FOR_DIALOGS = WS_SYSMENU | WS_POPUP; + +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Macros and typedefs +//******************************************************************** +////////////////////////////////////////////////////////////////////// + +#define MSG_HOOK ( L"MSG_HOOK" ) +#define MSG_UNHOOK ( L"MSG_UNHOOK" ) + +//// +// Each DLL instance (All Instances) need to keeps track of the following +// Data members (these end up being the same values so no need to put them into the DS) +//// +HINSTANCE s_hModule = NULL; +UINT m_WMHook = NULL; +UINT m_WMUnHook = NULL; + +// enum to send MSG_HOOK and MSG_UNHOOK +typedef enum _MSG{_MSG_HOOK,_MSG_UNHOOK} MSG_; + +//// +// Each DLL instance (All instances not just the once whose window, +// we'll hook into) will hold a pointer to it's own +// CWHPaccess Object. (allowing it access to the Shared Data Segment) +//// +CWHPaccess* s_ButtonHookAccess = NULL; + +//// +// Each DLL instanc needs to keep track of it's recently closed windows +//// +#define NCLOSES_TO_TRACK 25 +// timeout values, we need to ignore activate messages for nTime when +// we unhook to avoid rehooking again in processes that have multiple windows +const int IGNORE_ACTIVATE_MESSAGE_TIMEOUT_MS = 150; +struct RecentWindowsWTimeouts +{ + HWND hWnd; + DWORD dwTimeInserted; +}; +RecentWindowsWTimeouts s_hRecentClosedWindows[NCLOSES_TO_TRACK] = {NULL,NULL}; +UINT s_HRecentListI = 0; + +////////////////////////////////////////////////////////////////////// +// Func: InsertRecentClosedWindow() +// Desc: Insert a recently closed window +////////////////////////////////////////////////////////////////////// +void InsertRecentClosedWindow(HWND hWnd) +{ + RecentWindowsWTimeouts recent; + recent.hWnd = hWnd; + recent.dwTimeInserted = GetTickCount(); + + s_hRecentClosedWindows[s_HRecentListI] = recent; + s_HRecentListI = s_HRecentListI + 1; + + if(s_HRecentListI == NCLOSES_TO_TRACK) + s_HRecentListI = 0; +} +////////////////////////////////////////////////////////////////////// +// Func: FindRecentClosedWindow() +// Desc: Find a recently closed window +////////////////////////////////////////////////////////////////////// +BOOL FindRecentClosedWindow(HWND hWnd) +{ + DWORD dwTickCount = GetTickCount(); + for (UINT i = 0; i < s_HRecentListI; ++i) + { + if(s_hRecentClosedWindows[i].hWnd == hWnd) + { + DWORD diffTime = dwTickCount - s_hRecentClosedWindows[i].dwTimeInserted; + if(diffTime < IGNORE_ACTIVATE_MESSAGE_TIMEOUT_MS) + return true; + else + return false; + } + } + return false; +} +bool IsAWindowToHookInto(HWND hwnd); +////////////////////////////////////////////////////////////////////// +// Func: EnumProc() +// Desc: Hook/Unhook all top level windows. Called for every top-level +// Window on the screen. +// +// Prms: lParam, if true send Hook Message, false send UnHook Msg +// +// Retr: TRUE, always +////////////////////////////////////////////////////////////////////// +BOOL CALLBACK EnumProc( HWND hWnd, LPARAM lParam ) +{ + switch (lParam) + { + case _MSG_HOOK: + if((m_WMHook >= 0xC000) && (m_WMHook <= 0xFFFF) && + (IsAWindowToHookInto(hWnd))) + { + log(LOGGING_DEBUG, L"Sending m_WMHook to hWnd %u Msg %u", hWnd, m_WMHook); + SendMessage( hWnd, m_WMHook, 0, 0 ); + } + break; + + case _MSG_UNHOOK: + if((m_WMUnHook >= 0xC000) && (m_WMUnHook <= 0xFFFF) && + /* Check if Window is hooked into */ + ( s_ButtonHookAccess->FindHookedWnd(hWnd) == TRUE )) + { + log(LOGGING_DEBUG, L"Sending m_WMUnHook to hWnd %u Msg %u", hWnd, m_WMHook); + SendMessage( hWnd, m_WMUnHook, 0, 0 ); + } + break; + + default: + break; + } + + return TRUE; +} +////////////////////////////////////////////////////////////////////// +// Func: GetProcessNameFromPID() +// Retr: Returns the process name in the buffer and true if everything went well, +// false otherwise. +////////////////////////////////////////////////////////////////////// +bool GetProcessNameFromHWND(HWND hwnd, wchar_t strProcessNameBuf[MAX_PATH + 1]) +{ + DWORD pid = NULL; + GetWindowThreadProcessId(hwnd,&pid); + HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid ); + + // Get the process name + if (NULL != hProcess ) + GetModuleBaseName( hProcess, NULL, strProcessNameBuf, (MAX_PATH + 1)); + + CloseHandle(hProcess); + return true; +} +////////////////////////////////////////////////////////////////////// +// Func: IsWhiteListed() +// Desc: Function allows us to Blacklist certain windows to not be +// included when hooking the WinProcButton Hook. +// a Window can be whitelisted either on Title or Type, passed in +// thru the configuration +// +// Prms: hwnd, handle to a window we want to check +// +// Retr: true, if window is WhiteListed, false otherwise +////////////////////////////////////////////////////////////////////// +bool IsWhiteListed(HWND hwnd) +{ + wchar_t strBuf[MAX_PATH + 1] = {0}; + + if(GetProcessNameFromHWND(hwnd,strBuf)) + { + _wcsupr_s(strBuf,MAX_PATH); + if(s_ButtonHookAccess->IsAllowedProcessName(strBuf)) + return true; + } + + if (GetWindowText(hwnd,strBuf,MAX_PATH)) + { + _wcsupr_s(strBuf,MAX_PATH); + if(s_ButtonHookAccess->IsAllowedWindowsTitle(strBuf)) + return true; + } + + if(GetClassName(hwnd,strBuf,MAX_PATH)) + { + _wcsupr_s(strBuf,MAX_PATH); + if(s_ButtonHookAccess->IsAllowedWindowsClass(strBuf)) + return true; + } + + return false; +} +////////////////////////////////////////////////////////////////////// +// Func: IsFileOpenOrFileSaveAsDialog() +// Desc: We also hook into FileOpen and FileSaveAs Dialogs(), in order +// to do so we compare the window class +// +// Retr: true, if dialog is of a fileopen/filesaveas class, false otherwise +////////////////////////////////////////////////////////////////////// +bool IsFileOpenOrFileSaveAsDialog(HWND hwnd) +{ + wchar_t strBuf[MAX_PATH + 1] = {0}; + if(GetClassName(hwnd,strBuf,MAX_PATH)) + { + _wcsupr_s(strBuf); + if(lstrcmp(strBuf, L"#32770") == 0) + return true; + } + return false; +} +////////////////////////////////////////////////////////////////////// +// Strc: FileNameAndLocationStruct() +// Desc: We use this to pass out location and file name by EnumFileNameAndLocationProc +////////////////////////////////////////////////////////////////////// +struct FileNameAndLocationStruct +{ + wchar_t location[MAX_PATH + 1]; + wchar_t filename[MAX_PATH + 1]; + wchar_t filetypes[MAX_PATH + 1]; +}; +////////////////////////////////////////////////////////////////////// +// Func: EnumFileNameAndLocationProc() +// Desc: Iterate all child windows and extract FileName and FileLocation +// +// Prms: lParam, a FileNameAndLocationStruct* +// +// Retr: TRUE, always +////////////////////////////////////////////////////////////////////// +BOOL CALLBACK EnumFileNameAndLocationProc( HWND hWnd, LPARAM lParam ) +{ + wchar_t strWindowText[MAX_PATH + 1] = {0}; + wchar_t strClassName[MAX_PATH + 1] = {0}; + GetWindowText(hWnd, strWindowText, MAX_PATH); + GetClassName(hWnd, strClassName, MAX_PATH); + + bool bContinue = false; + // We only care about the following 3 window classes + // all others continue iteration + if((lstrcmp(L"Edit", strClassName) == 0) || + (lstrcmp(L"ComboBox", strClassName) == 0) || + (lstrcmp(L"ToolbarWindow32", strClassName) == 0)) + { + bContinue = true; + } + + // skip this window + if(!bContinue) + return TRUE; + + // passed in file struct pointer + FileNameAndLocationStruct* pstruct = (FileNameAndLocationStruct*) lParam; + + // Stop if there is no window text + if(lstrlen(strWindowText) <= 0) + return TRUE; + + // ignore any window texts that have an & + if(wcsstr(strWindowText, L"&")) + return TRUE; + + // * Good for Debugging * + //log(LOGGING_DEBUG, L"Found Window Text - %s ", strWindowText); + + // File Types Window Text (pass out in case it's needed later) + if(wcsstr(strWindowText, L"*.")) + { + log(LOGGING_DEBUG, L"Found FileType Text %s", strWindowText); + lstrcpy(pstruct->filetypes,strWindowText); + return TRUE; + } + + // Is this a location text + if(wcsstr(strWindowText, L": ")) // This could be very much English Windows Specific (or not?, should check) + { + // get the location of ": " + int i = 0; + wchar_t* pBegin = strWindowText; + for (; i < MAX_PATH; ++i) + { + if((*pBegin == L':') && (*(pBegin + 1) == L' ')) + { + pBegin = pBegin + 2; // start after the ": " + break; + } + ++pBegin; + } + + if(pBegin != NULL) + { + log(LOGGING_DEBUG, L"Found Location Text %s", pBegin); + lstrcpy(pstruct->location,pBegin); + } + return TRUE; + } + + // illegal file name characters + wchar_t* illegalfilechars = L"\\/:*?\"<>|"; + int illegalsize = lstrlen(illegalfilechars); + + if(wcsstr(strWindowText,L".")) + { + // check to see if string contains any illegal + // file name characters + for(int i = 0; i < illegalsize; ++i) + { + wchar_t c[2] = {0}; + c[0] = illegalfilechars[i]; + + // found illegal character, ignore string as file name + if(wcsstr(strWindowText,c)) + return TRUE; + } + + // Found a 100% file name string (it contains a '.') + log(LOGGING_DEBUG, L"Found FileName Text %s", strWindowText); + lstrcpy(pstruct->filename,strWindowText); + return TRUE; + } + else if(lstrlen(strWindowText) >= 1) + { + // check to see if string contains any illegal + // file name characters + for(int i = 0; i < illegalsize; ++i) + { + wchar_t c[2] = {0}; + c[0] = illegalfilechars[i]; + + // found illegal character, ignore string as file name + if(wcsstr(strWindowText,c)) + return TRUE; + } + + // Found a possible Most likely file name string (must not contain a '.') + log(LOGGING_DEBUG, L"Found FileName Text %s", strWindowText); + lstrcpy(pstruct->filename,strWindowText); + return TRUE; + } + + return TRUE; +} +////////////////////////////////////////////////////////////////////// +// Func: GetFileNameAndLocationStringValuesFromDialogWindow() +// Desc: Iterates through all the child windows and get the values we need +// and pass them back out +// +// Prms: hwnd, handle the fileOpen dialog +// pCallerObj, WPFCaller object where we will write the retrieved information to +////////////////////////////////////////////////////////////////////// +bool GetFileNameAndLocationStringValuesFromDialogWindow(HWND hwnd, WPFCaller* pCallerObj) +{ + // Iterate all child Windows and parse all the texts, the enum function + // will do all the work + if(hwnd && ::IsWindow(hwnd)) + { + // Clear any old values in the caller object + memset(pCallerObj->m_strFileNameLocationBuf, 0, sizeof(pCallerObj->m_strFileNameLocationBuf)); + memset(pCallerObj->m_strFileTypesBuf, 0, sizeof(pCallerObj->m_strFileTypesBuf)); + + // Create temporary object to hold values + FileNameAndLocationStruct filenameAndLocation; + memset(filenameAndLocation.filename, 0, sizeof(filenameAndLocation.filename)); + memset(filenameAndLocation.location, 0, sizeof(filenameAndLocation.location)); + memset(filenameAndLocation.filetypes, 0, sizeof(filenameAndLocation.filetypes)); + + // Try to Resolve + log(LOGGING_DEBUG, L"About to call EnumFileNameAndLocationProc (EnumChildWindows)"); + EnumChildWindows(hwnd, EnumFileNameAndLocationProc, (LPARAM) &filenameAndLocation ); + + // get resolving lengths + int nLen1 = lstrlen(filenameAndLocation.filename); + int nLen2 = lstrlen(filenameAndLocation.location); + int nLen3 = lstrlen(filenameAndLocation.filetypes); + + // Handle errors * Good for Debugging * + /* + if(nLen1 == 0) + log(LOGGING_DEBUG, L"Error resolving - FileName - FileOpen or FileSaveAs Dialog"); + if(nLen2 == 0) + log(LOGGING_DEBUG, L"Error resolving - FileLocation - FileOpen or FileSaveAs Dialog"); + if(nLen3 == 0) + log(LOGGING_DEBUG, L"Error resolving - FileTypes - FileOpen or FileSaveAs Dialog"); + */ + + // Something went wrong! no point moving on + if(nLen1 == 0 || nLen2 == 0 || nLen3 == 0) + return false; + + //// + // Now Copy out the values to the buffers of the caller object that was passed in + //// + lstrcpyn(pCallerObj->m_strFileNameLocationBuf, filenameAndLocation.location, MAX_PATH); + lstrcat(pCallerObj->m_strFileNameLocationBuf, L"\\"); + lstrcat(pCallerObj->m_strFileNameLocationBuf, filenameAndLocation.filename); + lstrcpyn(pCallerObj->m_strFileTypesBuf, filenameAndLocation.filetypes, MAX_PATH); + + // Log info to see what's going on + log(LOGGING_DEBUG, L"GetFileNameAndLocation setting m_strFileNameLocattionBuf to %s", pCallerObj->m_strFileNameLocationBuf); + log(LOGGING_DEBUG, L"GetFileNameAndLocation setting m_strFileTypesBuf to %s", pCallerObj->m_strFileTypesBuf); + return true; + + } + return false; +} +////////////////////////////////////////////////////////////////////// +// Func: IsAWindowToHookInto() +// Desc: Broad check to see if we want to hook into a window. +// Called by CallWndHookProc. +// Window on the screen. +// +// Prms: hwnd, handle to a window we want to check// +// +// Note: This function calls IsBlackListed() for more window exclusions. +// +// Retr: true, if window is should be hooked into, false otherwise +////////////////////////////////////////////////////////////////////// +bool IsAWindowToHookInto(HWND hwnd) +{ + DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); + DWORD dwExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + + if ( /* top-raised windows */ + ( ( dwExStyle & WS_EX_WINDOWEDGE ) == WS_EX_WINDOWEDGE ) + + /* Styles to test for (named above) */ + && ( ( dwStyle & WS_STYLES_TO_TEST_FOR ) == WS_STYLES_TO_TEST_FOR ) + + /* Has no parent = top-level window */ + && ( GetParent(hwnd) == NULL ) + + /* Check if Window is not already hooked into*/ + && ( s_ButtonHookAccess->FindHookedWnd(hwnd) == FALSE ) + + /* Check if Window has not been recently closed in this process*/ + && ( FindRecentClosedWindow(hwnd) == FALSE ) + + // **** CUSTOM INCLUSION LIST **** + && ( IsWhiteListed(hwnd) ) + + // Make sure the window is visible to begin with * bug fix for ms word* + && ( ::IsWindowVisible(hwnd)) + ) + { + return true; + } + else if ( // We also want to hook into the FileOpen & FileSaveAs Dialog + + /* top-raised windows */ + ( ( dwExStyle & WS_EX_WINDOWEDGE ) == WS_EX_WINDOWEDGE ) + + /* Styles to test for (named above) */ + && ( ( dwStyle & WS_STYLES_TO_TEST_FOR_DIALOGS ) == WS_STYLES_TO_TEST_FOR_DIALOGS ) + + /* Has a parent = it is a top-level window with parent */ + && ( GetParent(hwnd) != NULL ) + + /* Check if Window's parent is hooked into */ + && ( s_ButtonHookAccess->FindHookedWnd(GetParent(hwnd)) == TRUE ) + + /* Check if Window is not already hooked into*/ + && ( s_ButtonHookAccess->FindHookedWnd(hwnd) == FALSE ) + + /* Check if Window has not been recently closed in this process*/ + && ( FindRecentClosedWindow(hwnd) == FALSE ) + + // **** CUSTOM INCLUSION LIST **** + && ( IsWhiteListed(GetParent(hwnd)) ) + + // Make sure the window's parent is visible to begin with * bug fix for ms word * + && ( ::IsWindowVisible(GetParent(hwnd))) + + // * We currently hook only into Top-Level FileOpen/SaveAs Dialogs + && ( IsFileOpenOrFileSaveAsDialog(hwnd) ) + ) + { + return true; + } + else + { + return false; + } +} +////////////////////////////////////////////////////////////////////// +// Func: HookWndProc() +// Desc: Function that implements the WndProc for every process that +// has the window we are looking for. This is code is shared within +// the process on every window in the system. +// +// Note: This function is just the WndProc() Implementation +// All we have to do is process it if we care for it or pass it down +// to the next hook (that may be in the system). +// +// Prms: hWnd, handle to window +// Msg, passed in message +// wParam, specifies additional message information +// lParam, specifies additional message information +// +// Retr: LRESULT, +////////////////////////////////////////////////////////////////////// +LRESULT CALLBACK MyWndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) +{ + // default return + LRESULT result = 0; + + // Get the HookWndItem Information + BLANK_HookWndItem(item); + item = s_ButtonHookAccess->GetHookedWndItem(hWnd); + + bool bCloseMsg = ((Msg == WM_NCDESTROY) || (Msg == WM_DESTROY) || (Msg == WM_CLOSE)); + if(bCloseMsg) + log(LOGGING_DEBUG, L"Received WM_NCDESTROY or DESTROY MESSAGE or WM_CLOSE for window %u", item.hWnd); + + // Is this is a Window that is hooked? --- Ignore FileOpen / SaveDialog (Deal with them below) + if((item.hWnd != NULL) && (hWnd == item.hWnd) && !IsFileOpenOrFileSaveAsDialog(item.hWnd)) + { + //// + // Create wpfcaller object for this Window, if it doesn't exist + // ~Every wpfcaller is mapped to a single HookWndItem + //// + if(item.wpfcaller == NULL) + { + log(LOGGING_DEBUG, L"Creating a wpfCaller Instance for window %u", item.hWnd); + item.wpfcaller = new WPFCaller(item, s_hModule); + } + + //// + // Case StopHook wants us to Unhook the WmProc Hook or + // the Window gets Closed + //// + if ( (Msg == m_WMUnHook) || bCloseMsg ) + { + log(LOGGING_MEDIUM, L"Received WMUnook or bCloseMsg message for window %u", item.hWnd); + + // No Longer need to monitor this Window + s_ButtonHookAccess->DeleteHookedWnd(item.hWnd); + InsertRecentClosedWindow(item.hWnd); + + // Unhook Our WndProc Procedure (put the old one back) + log(LOGGING_MEDIUM, L"Unhooking a Window %u from the HookWndProc", item.hWnd); + SetWindowLong(hWnd,GWL_WNDPROC,(LONG) item.DefWndProc); + + // Delete this Window's CaptionButton Object + if(item.wpfcaller != NULL) + { + log(LOGGING_DEBUG, L"Deleting a wpfCaller Instance for Window %u", item.hWnd); + delete item.wpfcaller; + } + + // Call the old WindProc to handle Close message + if(bCloseMsg) + result = CallWindowProc( item.DefWndProc, hWnd, Msg, wParam, lParam ); + } + // All other Messages + else + { + // FOR TESTING - Skip Handling of Messages (Below) + // result = CallWindowProc( item->DefWndProc, hWnd, Msg, wParam, lParam ); + try + { + // the wpfCaller Handles all other Messages + if(item.wpfcaller != NULL) + result = item.wpfcaller->OnDefault( hWnd, Msg, wParam, lParam); + else + result = CallWindowProc( item.DefWndProc, hWnd, Msg, wParam, lParam); + } + catch(...) + { + log(LOGGING_LOW, L"*Error* Occured calling WpfCaller->OnDefault()"); + } + } + } + else if((item.hWnd != NULL) && (hWnd == item.hWnd) && IsFileOpenOrFileSaveAsDialog(item.hWnd)) // Deal with FileOpen / FileSave Dialog Here + { + //// + // Case StopHook wants us to Unhook the WmProc Hook or + // the Window gets Closed + //// + if ( (Msg == m_WMUnHook) || bCloseMsg ) + { + log(LOGGING_DEBUG, L"FileOpenOrFileSaveDialog() Received WMUnook or bCloseMsg message for Window %u", item.hWnd); + + // No Longer need to monitor this Window + s_ButtonHookAccess->DeleteHookedWnd(item.hWnd); + InsertRecentClosedWindow(item.hWnd); + + // Unhook Our WndProc Procedure (put the old one back) + log(LOGGING_DEBUG, L"FileOpenOrFileSaveDialog() Unhooking from the HookWndProc for Window %u", item.hWnd); + SetWindowLong(hWnd,GWL_WNDPROC,(LONG) item.DefWndProc); + + // Call the old WindProc to handle Close message + if(bCloseMsg) + { + // Handle CLose Message + result = CallWindowProc( item.DefWndProc, hWnd, Msg, wParam, lParam ); + } + } + else if((Msg == WM_COMMAND) && (LOWORD(wParam) == 1)) // Received Ok or Open Button + { + log(LOGGING_DEBUG, L"Reveived Command Message from Dialog Button %u - Ok or Open Button",LOWORD(wParam)); + // First Let's get the WPFCaller Instance of the main window and let it know that this occured + BLANK_HookWndItem(itemTmp); + itemTmp = s_ButtonHookAccess->GetHookedWndItem(GetParent(hWnd)); + + if(itemTmp.hWnd != NULL && itemTmp.wpfcaller != NULL) + { + // we want to obtain the File Location & File Name & File Types from the Dialogs + // ~this is the whole point why we hooked into it + log(LOGGING_DEBUG, L"Calling GetFileNameAndLocationStringValuesFromDialogWindow()"); + if((GetFileNameAndLocationStringValuesFromDialogWindow(hWnd, itemTmp.wpfcaller)) && + (lstrlen(itemTmp.wpfcaller->m_strFileNameLocationBuf) > 0)) + { + log(LOGGING_DEBUG, L"About to post WM_CLIENT_EVENT_OPENFILEORSAVEASDIALOGOCCURED to WPFCallerThread"); + log(LOGGING_DEBUG, L"Found FileNameLocation - %s", itemTmp.wpfcaller->m_strFileNameLocationBuf); + log(LOGGING_DEBUG, L"Found FileTypes - %s", itemTmp.wpfcaller->m_strFileTypesBuf); + + // Post to the WPFCallerThread that this Event Occured + // WM_CLIENT_EVENT_OPENFILEORSAVEASDIALOGOCCURED (WM_USER + 808) + PostThreadMessage(itemTmp.wpfcaller->m_threadID, (WM_USER + 808),0,0); + } + else + { + // This should resolve now since we are looking only for command id 1 + log(LOGGING_LOW, L"FileOpenOrFileSaveDialog() Error - GetFileNameAndLocationStringValuesFromDialogWindow Failed!"); + } + } + else + { + log(LOGGING_LOW, L"FileOpenOrFileSaveDialog() Error - Couldn't fetch Parents WPFCaller object - skipping file resolution"); + } + } + + // Forward all Messages + result = CallWindowProc(item.DefWndProc, hWnd, Msg, wParam, lParam); + } + + return result; +} +////////////////////////////////////////////////////////////////////// +// Func: CallWndHookProc() +// Desc: Function that will replace the normal WndProc with the HookWndProc +// procedure. It will do that for every process on the system that +// has a window. It will assign the function HookWndProc() +// +// Prms: nCode [in] = if == HC_ACTION CallWndHookProc must process the message +// wParam [in] = specifies if message is send by current process +// non-zero if it is current process, null otherwise +// LPARAM [in] = pointer to a CWPRETSTRUCT that contains details about the message +// +// Note: see MSDN for CallWndRetProc Function passed in with SetWindowHookEx +// ~We don't check wParam (pass directly thru) because we want to process all messages +// for all processes and don't care where it originates +// +// IMP!: In this function we check the Window and decide whether to display the button or not +// ~!IMP) WH_CALLWNDPROC hook is called in the context of the thread that calls SendMessage +// +// Retr: LRESULT, +////////////////////////////////////////////////////////////////////// +LRESULT WINAPI CallWndHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + + if (nCode == HC_ACTION) + { + LPCWPSTRUCT pCwp = (LPCWPSTRUCT) lParam; + + // Do we care about this Window?, We don't want to hook into all Windows + if(IsAWindowToHookInto(pCwp->hwnd)) + { + // Do we care about this Message? + if((pCwp->message == m_WMHook) /* We'll receive the Hook Message StartButtonHook is called */ + || (pCwp->message == WM_NCACTIVATE) /* Activates & deactivates a window, caption is redrawn. */ + || (pCwp->message == WM_CREATE) /* A new window is being created */ + || (pCwp->message == WM_ACTIVATE) /* a window is being activated */ + || (pCwp->message == WM_PAINT) /* I added this after figguring out that drag n' droped files don't trigger above messages */ + || (pCwp->message == WM_NCPAINT) /* Same as for WM_PAINT */ + ) + { + + // Log that we are hooking into a FileOpen Or FileSaveAsDialog + if(IsFileOpenOrFileSaveAsDialog(pCwp->hwnd)) + log(LOGGING_DEBUG, L"FileOpenOrFileSaveDialog() We are hooking into a FileOpen or FileSaveDialog"); + + // Create a hook Item, We are ready to hook into this Window + HookWndItem item; + + // hWnd = the handle to the current window + // DefWndProc = handle of the this window procedure (the address that is replaced by our Hook Function) + // HookWndProc = the address of this DLL instance's HookWndProc Function + item.hWnd = pCwp->hwnd; + item.DefWndProc = reinterpret_cast(GetWindowLong(pCwp->hwnd,GWL_WNDPROC)); + item.HookWndProc = MyWndProc; + item.wpfcaller = NULL; // The Caption Button will be initialized by MyHookWnd + + // Add the hook Item to the Global List + s_ButtonHookAccess->InsertHookedWndItem(item); + + //// + // ********************** INSTALL THE NEW WNDHOOK_PROCEDURE ********************** + // ******************************************************************************* + // GWL_WNDPROC - Sets a new address for the window procedure (WinProc()) + // Windows NT/2000/XP: You cannot change this attribute if the window does not + // belong to the same process as the calling thread. */The hook is responsible for + // putting the .dll into the memoryspace of every process. This Dll iterates thru + // all the Windows and right here hooks into the WndProc + //// + log(LOGGING_LOW, L"Installing HookWndProc for Window %u", pCwp->hwnd); + + // We have to call SetWindowLongPtr to install the WNDPROC. Not doins so causes + // our UnHook message to never be received by the Hooked Wnd + int result = SetWindowLongPtr( pCwp->hwnd, GWL_WNDPROC, (LONG) MyWndProc ); + } + } + } + + // We now pass in our Hook Handle down the current hook chain (in case other hooks are listening) + return (CallNextHookEx( s_ButtonHookAccess->get_hHook(), nCode, wParam, lParam )); +} +////////////////////////////////////////////////////////////////////// +// Func: Helper_ReadSafeArrayIntoWCharArr() +// Desc: Small Helper function to quickly read a SafeArray Into a WChar Array +// +// Prms: +pDes, char destination buffer to copy into +// -size, passes out the size of the safearray +// +pSrc, the Safearray source to copy from +// +// Note: Not much safety checking going on. Make sure the buffer has enough space! +// ~also only 1 dimensional arrays/safearrays work +// +// IMP!: MAX_PATH is the ultimate Max of size and elements of the pDest Buffer +////////////////////////////////////////////////////////////////////// +void Helper_ReadSafeArrayIntoWCharArr(wchar_t pDes[MAX_PATH][MAX_PATH],UINT& size,SAFEARRAY* pSrc) +{ + try + { + // this func only handles 1-dim arrays/safearrays + const int ONE_DIMENSIONAL = 1; + + long lUBound = 0; + long lLBound = 0; + SafeArrayGetLBound(pSrc, ONE_DIMENSIONAL, &lLBound); + SafeArrayGetUBound(pSrc, ONE_DIMENSIONAL, &lUBound); + + BSTR* pBSTR; + SafeArrayAccessData(pSrc, (void**) &pBSTR); + for (long n = lLBound; ((n <= lUBound) && (n < MAX_PATH)); ++n) + { + _bstr_t bstr(pBSTR[n], true); + lstrcpyn(&pDes[n][0],(wchar_t*) bstr , MAX_PATH); + } + SafeArrayUnaccessData(pSrc); + + // pass out the size + size = lUBound - lLBound + 1; + + // pSrc was empty so set size to 0 + if((size == 1) && (pDes[0][0] == 0)) + size = 0; + } + catch(...) + { + return; + } +} +////////////////////////////////////////////////////////////////////// +// Func: ReadOoganizerSettings() +// Desc: Calls OoganizerSettings COM Object to read in all the settings +// into our SharedDS. +// +// These are the important settings we need like Logging details, +// What windows to hook into, what window classes, and even +// window layout as well as debugging options +// +// Retr: true, if settings were read, false otherwise +////////////////////////////////////////////////////////////////////// +bool ReadOoganizerSettings() +{ + try + { + IOoganizerSettingsPtr pSettings(__uuidof(OoganizerSettingsAcc)); + + // Read Configuration File + _configurationPtr config = NULL; + if(FAILED(pSettings->ReadConfigXMLFile(&config))) + return false; + + // Get ButtonHook Settings + _ButtonHookSettingsPtr buttonhookSettings = NULL; + if(FAILED(config->get_ButtonHook(&buttonhookSettings))) + return false; + + // Let's do that First! ~Imp! Get/Set LogPath & Debug Settings + _bstr_t LogPath; + _LoggingSettingsPtr logSettings; + buttonhookSettings->get_LogSettings(&logSettings); + logSettings->get_LogPath(LogPath.GetAddress()); + s_ButtonHookAccess->SetLogPath((wchar_t*) LogPath); + log(LOGGING_DEBUG, L"Setting Log Path: %s", (wchar_t*) LogPath); + + // Logging Detail + unsigned long nLoggingDetail = 0; + logSettings->get_LoggingDetail(&nLoggingDetail); + s_ButtonHookAccess->SetLoggingDetail(static_cast(nLoggingDetail)); +#ifdef _DEBUG + log(LOGGING_DEBUG, L"Setting Log Detail: 4 (DEBUG)", nLoggingDetail); +#else + log(LOGGING_DEBUG, L"Setting Log Detail: %u", nLoggingDetail); +#endif + + //// + // Now set this instance's Logging option + //// + SetLoggingDetail(s_ButtonHookAccess->GetLoggingDetail(),s_ButtonHookAccess->GetLogPath()); + + SAFEARRAY* safeArray; + + // Get AllowedProcessNames + _AllowedProcessNamesWPtr processNames; + buttonhookSettings->get_AllowedProcessNames(&processNames); + processNames->get_ProcessName(&safeArray); + Helper_ReadSafeArrayIntoWCharArr(s_ButtonHookAccess->ALLOWED_PROCESS_NAMES,s_ButtonHookAccess->NUMBER_OF_ALLOWED_PROCESS_NAMES,safeArray); + + // log values + if(s_ButtonHookAccess->NUMBER_OF_ALLOWED_PROCESS_NAMES) + { + for (UINT i = 0; i < s_ButtonHookAccess->NUMBER_OF_ALLOWED_PROCESS_NAMES; ++i) + log(LOGGING_DEBUG, L"AllowedProcessName: %s", s_ButtonHookAccess->ALLOWED_PROCESS_NAMES[i]); + } + + // Get AllowedWindowTitles + _AllowedWindowTitlesWPtr windowTitles; + buttonhookSettings->get_AllowedWindowTitles(&windowTitles); + windowTitles->get_WindowTitle(&safeArray); + Helper_ReadSafeArrayIntoWCharArr(s_ButtonHookAccess->ALLOWED_WINDOW_TITLES,s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_TITLES,safeArray); + + // log values + if(s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_TITLES) + { + for (UINT i = 0; i < s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_TITLES; ++i) + log(LOGGING_DEBUG, L"AllowedWindowTitle: %s", s_ButtonHookAccess->ALLOWED_WINDOW_TITLES[i]); + } + + // Get AllowedWindowClasses + _AllowedWindowClassesWPtr windowClasses; + buttonhookSettings->get_AllowedWindowClasses(&windowClasses); + windowClasses->get_WindowClass(&safeArray); + Helper_ReadSafeArrayIntoWCharArr(s_ButtonHookAccess->ALLOWED_WINDOW_CLASSES,s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_CLASSES,safeArray); + + // log values + if(s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_CLASSES) + { + for (UINT i = 0; i < s_ButtonHookAccess->NUMBER_OF_ALLOWED_WINDOW_CLASSES; ++i) + log(LOGGING_DEBUG, L"AllowedWindowClass: %s", s_ButtonHookAccess->ALLOWED_WINDOW_CLASSES[i]); + } + return true; + } + catch(...) + { + return false; + } +} +////////////////////////////////////////////////////////////////////// +// Func: SystemMetricsTesterHELPER() +// Desc: Use this for Debugging only when you need to know certain system metrics values +////////////////////////////////////////////////////////////////////// +void SystemMetricsTesterHELPER() +{ + int k = 0; + k = GetSystemMetrics(SM_CXEDGE); //2 on vista + k = GetSystemMetrics(SM_CYEDGE); //2 on vista + + k = GetSystemMetrics(SM_CXFRAME); //8 on vista + k = GetSystemMetrics(SM_CYFRAME); //8 on vista + + k = GetSystemMetrics(SM_CXFIXEDFRAME); //3 on vista + k = GetSystemMetrics(SM_CYFIXEDFRAME); //3 on vista + + k = GetSystemMetrics(SM_CXMIN); //124 on vista + k = GetSystemMetrics(SM_CYMIN); //36 on vista + + k = GetSystemMetrics(SM_CXBORDER); // 1 on vista + k = GetSystemMetrics(SM_CYBORDER); // 1 on vista + + k = GetSystemMetrics(SM_CXSIZE); //32 on vista + k = GetSystemMetrics(SM_CYSIZE); //19 on vista + + k = GetSystemMetrics(SM_CYCAPTION); //20 on vista + //k = GetSystemMetrics(SM_CXCAPTION); + + k = GetSystemMetrics(SM_CYSMCAPTION); //18 on vista + //k = GetSystemMetrics(SM_CXSMCAPTION); + + k = GetSystemMetrics(SM_CYSMSIZE); //17 on vista + k = GetSystemMetrics(SM_CXSMSIZE); //17 on vista +} +////////////////////////////////////////////////////////////////////// +// Func: StartWinProcButtonHook() +// Desc: Exported DLL function to allow a process to start/attach +// the system WinProcButtonhook. This function will attach the WinProc function +// to the process's window via the CallWndHookProc() function +// +// Note: We'll check if the system is supported here. We'll only allow +// to start the hook, if that is the case +// +// Retr: TRUE, if succesfully attached, FALSE otherwise (i.e. OS NOT SUPPORTED) +////////////////////////////////////////////////////////////////////// +BOOL WINAPI StartButtonHook() +{ + // Debugging ONLY when we need certain values (comment/uncomment) + //SystemMetricsTesterHELPER(); + + // Let's try to see if we can force a rehook + bool bThereWasAnExistingHook = false; + if(s_ButtonHookAccess->get_hHook() != NULL) + { + s_ButtonHookAccess->set_hHook(NULL); + bThereWasAnExistingHook = true; + } + + // Global doesn't exist, we can start + if(s_ButtonHookAccess->get_hHook() == NULL) + { + // Delete All Shared Data Hook Data - Just in case previous DLL Instance corrupted HookData + s_ButtonHookAccess->ClearHookSData(); + + // Don't start ButtonHook unless the OS supports it + VARIANT_BOOL bIsSupported; + _EnvironmentCCWPtr env(__uuidof(EnvironmentCCW)); + env->IsWindowsOSSupported(&bIsSupported); + + if(bIsSupported == -1) // TRUE + { + bool bSettings = ReadOoganizerSettings(); + clearLog(); // Start Fresh (with a new Log) + + // We won't be able to log until we have read in the settings + if(bThereWasAnExistingHook) + log(LOGGING_LOW, L"A previous ButtonHook Existed - overwriting it"); + + if(!bSettings) + log(LOGGING_LOW, L"ReadOoganizerSettings Failed!"); + else + log(LOGGING_MEDIUM, L"ReadOoganizerSettings Succeeded"); + + // There really is no sense to start ButtonHook with no Settings Info + if(bSettings) + { + log(LOGGING_LOW, L"StartButtonHook Called()"); + + // Create/Store Global Hook (every instance needs access to this HOOK) + // ~WH_CALLWNDPROC hook is called in the context of the thread that calls SendMessage + log(LOGGING_DEBUG, L"Setting the Windows Hook"); + HHOOK hook = SetWindowsHookEx( WH_CALLWNDPROC, CallWndHookProc, s_hModule, 0 ); + + if(hook == NULL) + { + log(LOGGING_LOW, L"Windows Hook Failed error %i", GetLastError()); + return FALSE; + } + else + { + // Assign the hook value to the Global DS + log(LOGGING_DEBUG, L"Windows Hook Succeeded Hook Set %i", hook); + s_ButtonHookAccess->set_hHook(hook); + } + + // Send Hook Msg - This forces all windows already open in the system and that + // we want to hook into to load the captionbutton + + if(m_WMHook >= 0xC000 && m_WMHook <= 0xFFFF) + { + log(LOGGING_DEBUG, L"StartButtonHook - About to call EnumWindows"); + EnumWindows( EnumProc, _MSG_HOOK ); + log(LOGGING_LOW, L"StartButtonHook EnumWindows Returns - Everything is O.K."); + } + else + { + log(LOGGING_LOW, L"Registered Message m_WMHook is invalid - something is terribly wrong"); + return FALSE; + } + + return TRUE; + } + } + } + return FALSE; +} +////////////////////////////////////////////////////////////////////// +// Func: StopWinProcButtonHook() +// Desc: Exported DLL function to allow a process to stop/deattach +// the WinProcButton system hook +// +// Retr: TRUE, if succesfully deattached, FALSE otherwise +////////////////////////////////////////////////////////////////////// +BOOL WINAPI StopButtonHook() +{ + // Global does exist, we can exit + if(s_ButtonHookAccess->get_hHook() != NULL) + { + // Send UnHook Msg + if(m_WMUnHook >= 0xC000 && m_WMUnHook <= 0xFFFF) + { + log(LOGGING_LOW, L"StopButtonHook Called()"); + EnumWindows( EnumProc, _MSG_UNHOOK ); + log(LOGGING_LOW, L"StopButtonHook() EnumWindows Returns - Everything is O.K."); + } + else + { + log(LOGGING_LOW, L"Registered Message m_WMUnHook is invalid - something is terribly wrong"); + return FALSE; + } + + try + { + // now we can exit + if ( UnhookWindowsHookEx( s_ButtonHookAccess->get_hHook() ) != 0 ) + { + log(LOGGING_MEDIUM, L"Successfully Unhooked Hook %i", s_ButtonHookAccess->get_hHook()); + } + else + { + log(LOGGING_LOW, L"Error Occrured in StopButtonHook %i", GetLastError()); + return FALSE; + } + + // Reset Global Hook - Delete All Shared Data + log(LOGGING_HIGH, L"Reset Global Hook & Clearing ALL Hook Related Data"); + s_ButtonHookAccess->set_hHook(NULL); + s_ButtonHookAccess->ClearHookSData(); + + // New Code: ~errors out~ Unregister all Window Classes here (used to be done in ~WPFCaller()) + /*if(!UnregisterClass(L"W32ButtonHookWndClass", s_hModule)) + log(LOGGING_DEBUG, L"Error occured for UnregisterClass W32ButtonHookWndClass");*/ + } + catch(...) + { + log(LOGGING_LOW, L"Error occured in StopButtonHook"); + return FALSE; + } + return TRUE; + } + return FALSE; +} +////////////////////////////////////////////////////////////////////// +// Func: IsButtonHookSet() +// Desc: Exported DLL function to allow a caller to know if the buttonhook +// is set or not +// +// Retr: TRUE, if Hook is attached, FALSE otherwise +////////////////////////////////////////////////////////////////////// +BOOL WINAPI IsButtonHookSet() +{ + return (s_ButtonHookAccess->get_hHook() != NULL); +} +////////////////////////////////////////////////////////////////////// +// Func: GetAllHookedWindowHandles() +// Desc: Exported DLL function to allow a caller to retrieve all Hooked +// Window Handles. +// ~passed in pBuf must be at least of size MAX_PATH +// +// Retr: int, returns the size of the passed out pBuf list +////////////////////////////////////////////////////////////////////// +int WINAPI GetAllHookedWindowHandles(int* pBuf) +{ + if(s_ButtonHookAccess->get_hHook() != NULL) + { + int buf[MAX_PATH] = {0}; + int nsize = 0; + s_ButtonHookAccess->GetHookedWindowListNSize(buf,&nsize); + + //// + // there could be nulls in the buf, so filter them out, + // to return a complete list the caller. Copy only Non-Null + // values to the output buffer * and ONLY EXISTING WINDOWS * + //// + int nNullsOrInvalid = 0; + for(int i = 0; i < nsize; ++i) + { + if(buf[i] != NULL && ::IsWindow((HWND) buf[i])) + *(pBuf + i) = buf[i]; + else + ++nNullsOrInvalid; + } + + // return the adjusted size, if needed + log(LOGGING_DEBUG, L"GetAllHookedWindowHandles() got called returning WindowHandles Buf size of %u", (nsize - nNullsOrInvalid)); + return (nsize - nNullsOrInvalid); + } + return 0; +} +////////////////////////////////////////////////////////////////////// +// Func: DllMain() +// Desc: Dll Main Entry Point - The DLL is being attached to every +// process in the system! ~therefore it must be fast. Also +// we can't start the main register hook function from here +// system call from here. (because this dll get loaded many times, +// we only however want the system hook code to be called only once. +// +// Note: Attaching the dll will cause MSG_HOOK to be registred +// +// Retr: TRUE, always +////////////////////////////////////////////////////////////////////// +BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) +{ + + switch ( ul_reason_for_call ) + { + case DLL_PROCESS_ATTACH: + + // This is to access DS segment's Hook Information, + // Across all instances of this DLL. + s_ButtonHookAccess = new CWHPaccess(); + + // Store local Module Handle + s_hModule = (HINSTANCE) hModule; + + // message is used to send to all windows when the HOOK attaches + m_WMHook = RegisterWindowMessage( MSG_HOOK ); + + // message is used to send to all windows when the HOOK unattaches + m_WMUnHook = RegisterWindowMessage( MSG_UNHOOK ); + + // get the shared setting logging information and store it into this instance + SetLoggingDetail(s_ButtonHookAccess->GetLoggingDetail(), s_ButtonHookAccess->GetLogPath()); + + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_DETACH: + case DLL_THREAD_ATTACH: + default: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/Hooks/ButtonHook/ButtonHook.h b/Hooks/ButtonHook/ButtonHook.h new file mode 100644 index 0000000..0264782 --- /dev/null +++ b/Hooks/ButtonHook/ButtonHook.h @@ -0,0 +1,17 @@ +// ButtonHook.h +#pragma once +#include "CWHPaccess.h" + +#ifdef DLLAPI_BUTTON_HOOK +#define ENTRY_FUNCTION extern "C" _declspec(dllexport) +#else +#define ENTRY_FUNCTION extern "C" _declspec(dllimport) +#endif + +//// +// Entry-Point (Exposed)Functions +//// +ENTRY_FUNCTION BOOL WINAPI StartButtonHook(void); +ENTRY_FUNCTION BOOL WINAPI StopButtonHook(void); +ENTRY_FUNCTION BOOL WINAPI IsButtonHookSet(void); +ENTRY_FUNCTION int WINAPI GetAllHookedWindowHandles(int* pBuf); diff --git a/Hooks/ButtonHook/ButtonHook.vcproj b/Hooks/ButtonHook/ButtonHook.vcproj new file mode 100644 index 0000000..7c4a7bc --- /dev/null +++ b/Hooks/ButtonHook/ButtonHook.vcproj @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Hooks/ButtonHook/ButtonStrategy.cpp b/Hooks/ButtonHook/ButtonStrategy.cpp new file mode 100644 index 0000000..91024c9 --- /dev/null +++ b/Hooks/ButtonHook/ButtonStrategy.cpp @@ -0,0 +1,390 @@ +#include "StdAfx.h" +#include "ButtonStrategy.h" +//#include "HiddenWindow.h" // for Some Strategies we need to create + // a hidden window and draw the buttons on it + +//// +// We are delay-loading the UXTheme.dll. In case we are running on +// a system where the dll doesn't exist, we'll only load it we know +// that this is a system where it should exist +//// +#include "uxtheme.h" +//// +// We are delay-loading the DWMapi.dll. In case we are running on +// a system where the dll doesn't exist, we'll only load it we know +// that this is a system where it should exist +//// +#include "dwmapi.h" + +using namespace Ooganizer; + +//******************************************************************** +// Clss ButtonStrategy +// +// Programmer Daniel Romischer +// Ooganizer Development Team +// +// Description Base/Abstract Class for all Button Strategies +// +// Note CalcCaptionRect() and CalcCaptionButtonRect() +// is implemented in the base class for now (as it appears +// to be the same calculation for all Button Strategies). +// +// Created 06-01-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +ButtonStrategy::ButtonStrategy(void) +{ +} +ButtonStrategy::~ButtonStrategy(void) +{ +} +////////////////////////////////////////////////////////////////////// +// Func: CalcCaptionRect() +// Desc: Calculates the dimensions of the Caption Bar +// +// Prms: +hWnd, handle to a Windows +// +-Rect, returns the x,y RECT area dimension coordinates of the caption bar +// +-SIZE, returns the width and height of the Caption bar +////////////////////////////////////////////////////////////////////// +void ButtonStrategy::CalcCaptionRect(HWND hWnd, RECT &RectCaption, SIZE &heightNwidth)const +{ + RECT Rect; + SIZE sFrame; + DWORD dStyle = GetWindowLong( hWnd, GWL_STYLE ); + + // Get frame size of window + // (x and y height width dim of the resizable or non-resizable windows frame) + sFrame.cy = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME ); + sFrame.cx = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME ); + + // Gets the location of the Window + GetWindowRect( hWnd, &Rect ); + + // Height and Width of the Window + LONG height = Rect.bottom - Rect.top; // Window height not intersting to us (not used) + LONG width = Rect.right - Rect.left; + + // Pass the CaptionBar Dimension out + RectCaption.top = sFrame.cy; // 4, 8 + RectCaption.left = sFrame.cx; // 4, 8 + RectCaption.right = width - sFrame.cy; // 771 + + // SM_CYCAPTION = The height of a caption area, in pixels + // SM_CYBORDER = The height of a window border + int heightCaption = GetSystemMetrics( SM_CYCAPTION ); // 20 + int heightWindowBorder = GetSystemMetrics( SM_CYBORDER ); // 1 + + RectCaption.bottom = heightCaption; + + //heightCaption gives us the correct caption height, but in order to get the exact RECT location, + //calculated from top left, we need to add sFrame.cy to it. ~we substract the bottom border because, + //otherwise the height will be too long + + //sFrame.cy + heightCaption - heightWindowBorder; + + // sample return + // top = 4, left = 4, bottom = 23, right = 771 + + // Pass out the height & Width of the CaptionBar + heightNwidth.cx = heightCaption; + heightNwidth.cy = width; +} +//******************************************************************** +// Clss ClassicButtonStrategy +// +// Description Implementation for our Windows Classic Theme Strategy +// +// Note Uses DrawFrameControl() to draw the Button. This will +// Only work in Windows2000/XP without theme (classic View) +// +// Created 06-01-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +ClassicButtonStrategy::ClassicButtonStrategy() +{ +} +ClassicButtonStrategy::~ClassicButtonStrategy() +{ +} +////////////////////////////////////////////////////////////////////// +// Func: draw() +// Desc: generic draw function - called for all default messages +////////////////////////////////////////////////////////////////////// +void ClassicButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + // Use the regular Frame Control *Windows Classic* + // DrawFrameControl( hDc, const_cast(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH ); + + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonUp() +// Desc: draw the button in an up state +////////////////////////////////////////////////////////////////////// +void ClassicButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + // Use the regular Frame Control *Windows Classic* + // DrawFrameControl( hDc, const_cast(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH ); + + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonDown() +// Desc: draw the button in a down state +////////////////////////////////////////////////////////////////////// +void ClassicButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + // Use the regular Frame Control *Windows Classic* + // DrawFrameControl( hDc, const_cast(&rPos), DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED ); + + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +//******************************************************************** +// Clss AeroButtonStrategy +// +// Description Implementation for our Windows Aero Theme Strategy +// +// Note +// +// +// Created 06-01-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +AeroButtonStrategy::AeroButtonStrategy() +{ +} +AeroButtonStrategy::~AeroButtonStrategy() +{ +} +////////////////////////////////////////////////////////////////////// +// Func: CalcCaptionButtonRect() +// Desc: Calculates the dimensions of the Caption Button. Takes into +// account the number of caption buttons on the window and returns +// the pos (RECT) where to draw the Caption Button. +// +// Prms: +hWnd, handle to a Windows +// +-RectButtonPos, returns the x,y dimension of where to place the Button +////////////////////////////////////////////////////////////////////// +void AeroButtonStrategy::CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const +{ + // Button Constants + const LONG BUTTON_MARGIN = 2; // The Margin Space between the Buttons + + //The width of a button in a window caption or title bar, in pixels + const LONG CAPTION_WIDTH = GetSystemMetrics(SM_CXSIZE); // should be 28 + + log(LOGGING_HIGH, "Caption Width = %i", CAPTION_WIDTH); + + RECT rect; + SIZE size; + // Get The dimensions of the CaptionBar + CalcCaptionRect(hWnd,rect,size); + + // sample return from CalcCaptionRect() + // top = 4, left = 4, bottom = 23, right = 771 + + // On Aero the distance of the Button is 10 not 6. Calculating by multiplying top * 2 (=8) + // ~this makes sense because our Rect start at the top most location (not where vista wants to draw the button + const LONG TOP_PLACEMENT = (2 * rect.top) + BUTTON_MARGIN; + const LONG BOTTOM_PLACEMENT = rect.bottom - BUTTON_MARGIN; + + // Left and Right Placement has to be calculated using the spacing on the right, the caption button widths, + // of (close, max, min) and the margins in between the buttons. (RECT includes all caption buttons), + // we also subtract rect.top from the left because a window border on right is not considered (+ another margin) + const LONG RIGHT_PLACEMENT = rect.right - (CAPTION_WIDTH * 3) - (BUTTON_MARGIN * 3) - (rect.top + BUTTON_MARGIN); + const LONG LEFT_PLACEMENT = RIGHT_PLACEMENT - CAPTION_WIDTH; // - BUTTON_MARGIN? + + //// + // Pass out the dimension of the CaptionButton + //// + RectButtonPos.top = TOP_PLACEMENT; + RectButtonPos.bottom = BOTTOM_PLACEMENT; + RectButtonPos.right = RIGHT_PLACEMENT; + RectButtonPos.left = LEFT_PLACEMENT; +} +////////////////////////////////////////////////////////////////////// +// Func: draw() +// Desc: generic draw function - called for all default messages +////////////////////////////////////////////////////////////////////// +void AeroButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + // HTHEME hTheme = OpenThemeData(hWnd, L"OkButton;Button;Window"); + // HTHEME hTheme = OpenThemeData(hWnd, L"Button"); + + // DrawThemeParentBackground(hWnd,hDc,&rPos); + // DrawThemeBackground(hTheme,hDc,0,0,&rPos,0); + + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\VistaNoAero.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonUp() +// Desc: draw the button in an up state +////////////////////////////////////////////////////////////////////// +void AeroButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonDown() +// Desc: draw the button in a down state +////////////////////////////////////////////////////////////////////// +void AeroButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\bridge.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +//******************************************************************** +// Clss VistaNoAeroStrategy +// +// Description Implementation for Vista when Aero (Glass) is not running +// +// Note +// +// +// Created 06-01-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +VistaNoAeroStrategy::VistaNoAeroStrategy() +{ +} +VistaNoAeroStrategy::~VistaNoAeroStrategy() +{ +} +////////////////////////////////////////////////////////////////////// +// Func: CalcCaptionButtonRect() +// Desc: Calculates the dimensions of the Caption Button. Takes into +// account the number of caption buttons on the window and returns +// the pos (RECT) where to draw the Caption Button. +// +// Prms: +hWnd, handle to a Windows +// +-RectButtonPos, returns the x,y dimension of where to place the Button +////////////////////////////////////////////////////////////////////// +void VistaNoAeroStrategy::CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const +{ + // Button Constants + const LONG BUTTON_MARGIN = 2; // The Margin Space between the Buttons + + //The width of a button in a window caption or title bar, in pixels + const LONG CAPTION_WIDTH = GetSystemMetrics(SM_CXSIZE); // 32 (appears to include left and righ Margin) + + RECT rect; + SIZE size; + // Get The dimensions of the CaptionBar + CalcCaptionRect(hWnd,rect,size); + log(LOGGING_HIGH, "rect is top %i, bottom %i, left %i, right %i", rect.top, rect.bottom, rect.left, rect.right); + + // sample return from CalcCaptionRect() + + // Vista Aero + // top = 4, left = 4, bottom = 23, right = 771 + + // Vista NoAero + // rect is top 8, bottom 27, left 8, right 831 + + // On Aero the distance of the Button is 10 not 6. Calculating by multiplying top * 2 (=8) + // ~this makes sense because our Rect start at the top most location (not where vista wants to draw the button + const LONG TOP_PLACEMENT = 10; //(2 * rect.top) + BUTTON_MARGIN; + const LONG BOTTOM_PLACEMENT = rect.bottom - BUTTON_MARGIN; + + // Left and Right Placement has to be calculated using the spacing on the right, the caption button widths, + // of (close, max, min) and the margins in between the buttons. (RECT includes all caption buttons), + // we also subtract rect.top from the left because a window border on right is not considered (+ another margin) + // 96 + const LONG RIGHT_PLACEMENT = rect.right - 96; + const LONG LEFT_PLACEMENT = RIGHT_PLACEMENT - 28; // - BUTTON_MARGIN? + + //// + // Pass out the dimension of the CaptionButton + //// + RectButtonPos.top = TOP_PLACEMENT; + RectButtonPos.bottom = BOTTOM_PLACEMENT; + RectButtonPos.right = RIGHT_PLACEMENT; + RectButtonPos.left = LEFT_PLACEMENT; +} +////////////////////////////////////////////////////////////////////// +// Func: draw() +// Desc: generic draw function - called for all default messages +////////////////////////////////////////////////////////////////////// +void VistaNoAeroStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ + HICON hIcon = (HICON) LoadImage(NULL, L"C:\\VistaNoAero.ico", IMAGE_ICON, 28, 15, LR_LOADFROMFILE); + DrawIcon(hDc, rPos.left, rPos.top, hIcon); +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonUp() +// Desc: draw the button in an up state +////////////////////////////////////////////////////////////////////// +void VistaNoAeroStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonDown() +// Desc: draw the button in a down state +////////////////////////////////////////////////////////////////////// +void VistaNoAeroStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ +} +//******************************************************************** +// Clss XPButtonStrategy +// +// Description Implementation for Windows XP Themed Strategy +// +// Note +// +// +// Created 06-01-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +XPButtonStrategy::XPButtonStrategy() +{ +} +XPButtonStrategy::~XPButtonStrategy() +{ +} +////////////////////////////////////////////////////////////////////// +// Func: draw() +// Desc: generic draw function - called for all default messages +////////////////////////////////////////////////////////////////////// +void XPButtonStrategy::draw(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonUp() +// Desc: draw the button in an up state +////////////////////////////////////////////////////////////////////// +void XPButtonStrategy::drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ +} +////////////////////////////////////////////////////////////////////// +// Func: drawButtonDown() +// Desc: draw the button in a down state +////////////////////////////////////////////////////////////////////// +void XPButtonStrategy::drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const +{ +} \ No newline at end of file diff --git a/Hooks/ButtonHook/ButtonStrategy.h b/Hooks/ButtonHook/ButtonStrategy.h new file mode 100644 index 0000000..64605ac --- /dev/null +++ b/Hooks/ButtonHook/ButtonStrategy.h @@ -0,0 +1,102 @@ +#pragma once + +namespace Ooganizer +{ + ////////////////////////////////////////////////////////////////////// + // Itce: ButtonStrategy + // Desc: This interface allows us to abstract out specific implementations + // for different caption buttons with different Themes. + // + // Note: following functions will be called from the windows messages to + // be implemented directly here independently and draw only the button. + // + // Note2: Each Button Strategy is directly tied to a C + ////////////////////////////////////////////////////////////////////// + class ButtonStrategy + { + public: + // generic draw function - called for all default messages + virtual void draw(HWND hWnd, const HDC &hdc, const RECT &rpos) const = 0; + // draw the button in an up state + virtual void drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const = 0; + // draw the button in a down state + virtual void drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const = 0; + + // returns the RECT position of the the CaptionButton + virtual void CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const = 0; + + //// + // returns the dimension / size of the caption / title bar (impl. in base) + //// + void CalcCaptionRect(HWND hWnd, RECT& RectCaption, SIZE &heightNwidth) const; + + ButtonStrategy(void); + virtual ~ButtonStrategy(void); + }; + ////////////////////////////////////////////////////////////////////// + // Clss: ClassicButtonStrategy + // Desc: Implementation for our Windows Classic Theme Strategy + ////////////////////////////////////////////////////////////////////// + class ClassicButtonStrategy : public ButtonStrategy + { + public: + void draw(HWND hWnd, const HDC &hdc, const RECT &rpos) const; + void drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + void drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + + void CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const {}; + + ClassicButtonStrategy(); + virtual ~ClassicButtonStrategy(); + }; + ////////////////////////////////////////////////////////////////////// + // Clss: AeroButtonStrategy + // Desc: Implementation for our Windows Aero (Glass) Strategy + ////////////////////////////////////////////////////////////////////// + class AeroButtonStrategy : public ButtonStrategy + { + public: + virtual void draw(HWND hWnd, const HDC &hdc, const RECT &rpos) const; + void drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + void drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + + void CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const; + + AeroButtonStrategy(); + virtual ~AeroButtonStrategy(); + }; + ////////////////////////////////////////////////////////////////////// + // Clss: VistaNoAeroStrategy + // Desc: Implementation for Vista when Aero (Glass) is not running + ////////////////////////////////////////////////////////////////////// + class VistaNoAeroStrategy : public ButtonStrategy + { + public: + virtual void draw(HWND hWnd, const HDC &hdc, const RECT &rpos) const; + void drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + void drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + + void CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const; + + // Uses Hidden Window Strategy + VistaNoAeroStrategy(); + virtual ~VistaNoAeroStrategy(); + }; + ////////////////////////////////////////////////////////////////////// + // Clss: XPButtonStrategy + // Desc: Implementation for Windows XP Themed Strategy + ////////////////////////////////////////////////////////////////////// + class XPButtonStrategy : public ButtonStrategy + { + public: + + virtual void draw(HWND hWnd, const HDC &hdc, const RECT &rpos) const; + void drawButtonUp(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + void drawButtonDown(HWND hWnd, const HDC &hDc, const RECT &rPos) const; + + void CalcCaptionButtonRect(HWND hWnd, RECT& RectButtonPos) const{}; + + XPButtonStrategy(); + virtual ~XPButtonStrategy(); + }; +} \ No newline at end of file diff --git a/Hooks/ButtonHook/CWHPaccess.cpp b/Hooks/ButtonHook/CWHPaccess.cpp new file mode 100644 index 0000000..221381e --- /dev/null +++ b/Hooks/ButtonHook/CWHPaccess.cpp @@ -0,0 +1,414 @@ +#include "stdafx.h" +#include "CWHPaccess.h" + +using namespace Ooganizer; +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Global variables - Shared Data Segment (Shared across all instances +// of this dll!) +//******************************************************************** +////////////////////////////////////////////////////////////////////// +#pragma data_seg( ".CWHP" ) +HHOOK CWHPaccess::hHook = NULL; +HookWndItem CWHPaccess::HList[MAX_PATH] = {NULL,NULL,NULL,NULL}; +UINT CWHPaccess::HListI = 0; +wchar_t CWHPaccess::ALLOWED_PROCESS_NAMES[MAX_PATH][MAX_PATH] = {0}; +UINT CWHPaccess::NUMBER_OF_ALLOWED_PROCESS_NAMES = 0; +wchar_t CWHPaccess::ALLOWED_WINDOW_TITLES[MAX_PATH][MAX_PATH] = {0}; +UINT CWHPaccess::NUMBER_OF_ALLOWED_WINDOW_TITLES = 0; +wchar_t CWHPaccess::ALLOWED_WINDOW_CLASSES[MAX_PATH][MAX_PATH] = {0}; +UINT CWHPaccess::NUMBER_OF_ALLOWED_WINDOW_CLASSES = 0; +UINT CWHPaccess::nLoggingDetail = LOGGING_NONE; +wchar_t CWHPaccess::LoggingPath[MAX_PATH] = {0}; +#pragma data_seg() +#pragma comment( linker, "/SECTION:.CWHP,rws" ) +////////////////////////////////////////////////////////////////////// +// Constructor / Destructor +////////////////////////////////////////////////////////////////////// +CWHPaccess::CWHPaccess() +{ + InitializeCriticalSection(&cs); +} +CWHPaccess::~CWHPaccess() +{ + DeleteCriticalSection(&cs); +} +// Set/Get hHook +void CWHPaccess::set_hHook(HHOOK hook) +{ + EnterCS(); + hHook = hook; + LeaveCS(); +} +HHOOK CWHPaccess::get_hHook() +{ + return hHook; +} +// Public CRITICAL_SECTION Accessors +void CWHPaccess::EnterCS() +{ + EnterCriticalSection(&cs); +} +void CWHPaccess::LeaveCS() +{ + LeaveCriticalSection(&cs); +} +////////////////////////////////////////////////////////////////////// +// Func: ClearHookItem() +// Desc: Clears a single Hook Item +////////////////////////////////////////////////////////////////////// +void CWHPaccess::ClearHookItem(UINT nItem) +{ + if((nItem < 0) || (nItem >= MAX_PATH)) + return; + + HList[nItem].hWnd = NULL; + HList[nItem].DefWndProc = NULL; + HList[nItem].HookWndProc = NULL; + HList[nItem].wpfcaller = NULL; +} +////////////////////////////////////////////////////////////////////// +// Func: ClearHookSData() +// Desc: Clears all the data stored in the Shared DS segment's Hook List +////////////////////////////////////////////////////////////////////// +void CWHPaccess::ClearHookSData() +{ + EnterCS(); + hHook = NULL; + HListI = 0; + + for (int i=0; i < MAX_PATH; ++i) + ClearHookItem(i); + + LeaveCS(); +} +////////////////////////////////////////////////////////////////////// +// Func: InsertHookedWndItem() +// Desc: Inserts a HookWndItem into the Shared DS's HookedList +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::InsertHookedWndItem(HookWndItem &Item) +{ + BOOL bRetVal = FALSE; + EnterCS(); + for (UINT i = 0;i < MAX_PATH; ++i) + { + if(HList[i].hWnd == NULL) + { + HList[i] = Item; + + log(LOGGING_DEBUG, L"Inserting HookedItem into DS index = %i", i); + // Keep track of the list top index *performance* + if(i > HListI) + { + HListI = i; + log(LOGGING_DEBUG, L"Inserting HookedItem setting HListI = %i", HListI); + } + bRetVal = TRUE; + break; + } + } + LeaveCS(); + + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: FindHookedWnd() +// Desc: Finds Inserts a HookWndItem into the Shared DS's HookedList +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::FindHookedWnd(HWND hWnd) +{ + BOOL bRetVal = FALSE; + + EnterCS(); + for (UINT i = 0;i <= HListI;++i) + { + if(HList[i].hWnd == hWnd) + { + bRetVal = TRUE; + break; + } + } + LeaveCS(); + + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: GetHookedWndItem() +// Desc: Returns a matchin HookWndItem (.hWnd will be NULL if not found) +////////////////////////////////////////////////////////////////////// +HookWndItem CWHPaccess::GetHookedWndItem(HWND hWnd) +{ + BLANK_HookWndItem(retVal); + + EnterCS(); + for (UINT i = 0;i <= HListI;++i) + { + if(HList[i].hWnd == hWnd) + { + retVal = HList[i]; + } + } + LeaveCS(); + + return(retVal); +} +////////////////////////////////////////////////////////////////////// +// Func: GetHookedWindowListNSize() +// Desc: Use this to get a copy of the hooked window buffer and size in the Shared DS +////////////////////////////////////////////////////////////////////// +void CWHPaccess::GetHookedWindowListNSize(int* nbuf, int* nsize) +{ + EnterCS(); + + // write out the size + *nsize = HListI; + + for (UINT i = 0;i <= HListI;++i) + { + // write out the actual buffer + *(nbuf + i) = (int) HList[i].hWnd; + } + + LeaveCS(); +} +////////////////////////////////////////////////////////////////////// +// Func: SetHookedWndItem() +// Desc: Use this to overwrite Hook information for a window in the Shared DS +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::SetHookedWndItem(HWND hWnd, HookWndItem& Item) +{ + BOOL bRetVal = FALSE; + EnterCS(); + for (UINT i = 0;i <= HListI;++i) + { + if((HList[i].hWnd == hWnd) && + (hWnd == Item.hWnd)) + { + HList[i] = Item; + bRetVal = TRUE; + } + } + LeaveCS(); + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: DeleteHookedWnd() +// Desc: Finds Inserts a HookWndItem into the Shared DS's HookedList +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::DeleteHookedWnd(HWND hWnd) +{ + + BOOL retVal = FALSE; + EnterCS(); + // Is it the Last Item in the list? + if(HList[HListI].hWnd == hWnd) + { + ClearHookItem(HListI); + if(HListI > 0) + { + HListI = HListI - 1; + log(LOGGING_DEBUG, L"DeleteHookedWnd HListI set to %i", HListI); + } + + retVal = TRUE; + } + else + { + for (UINT i = 0; i <= HListI; ++i) + { + if(HList[i].hWnd == hWnd) + { + ClearHookItem(i); + deltaListTopI(i); + retVal = TRUE; + break; + } + } + } + LeaveCS(); + + return retVal; +} +////////////////////////////////////////////////////////////////////// +// Func: deltaListTopI() +// Desc: *for performance * adjusts the Top index responding to a delete +////////////////////////////////////////////////////////////////////// +void CWHPaccess::deltaListTopI(int deletedIndex) +{ + UINT i; + + EnterCS(); + for(i = deletedIndex + 1; i <= HListI; ++i) + { + if(HList[i].hWnd == NULL) + { + continue; + } + break; + } + if(i > HListI) + { + if(deletedIndex > 0) + { + HListI = deletedIndex - 1; + log(LOGGING_DEBUG, L"deltaListTopI HListI set to %i", HListI); + } + else + { + log(LOGGING_DEBUG, L"deltaListTopI HListI set to %i", HListI); + HListI = 0; + } + } + LeaveCS(); +} +////////////////////////////////////////////////////////////////////// +// Func: AddAllowedProcessName() +// Desc: Add Allowed Process Name +////////////////////////////////////////////////////////////////////// +void CWHPaccess::AddAllowedProcessName(wchar_t* strProcessNameInUpperCase) +{ + if(strProcessNameInUpperCase) + { + EnterCS(); + int i = NUMBER_OF_ALLOWED_PROCESS_NAMES; + lstrcpyn(ALLOWED_PROCESS_NAMES[i], strProcessNameInUpperCase, MAX_PATH - 1); + NUMBER_OF_ALLOWED_PROCESS_NAMES = i + 1; + LeaveCS(); + + log(LOGGING_DEBUG, L"Allowing Process %s", strProcessNameInUpperCase); + } + +} +////////////////////////////////////////////////////////////////////// +// Func: IsAllowedProcessName() +// Desc: Find Allowed Process Name +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::IsAllowedProcessName(wchar_t* strProcessNameInUpperCase) +{ + BOOL bRetVal = FALSE; + if(strProcessNameInUpperCase) + { + EnterCS(); + for (UINT i = 0; i < NUMBER_OF_ALLOWED_PROCESS_NAMES; ++i) + { + if(wcsstr(strProcessNameInUpperCase, ALLOWED_PROCESS_NAMES[i])) + { + bRetVal = TRUE; + break; + } + } + LeaveCS(); + } + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: AddAllowedApplication() +// Desc: Add Allowed Windows Titles +////////////////////////////////////////////////////////////////////// +void CWHPaccess::AddAllowedWindowsTitle(wchar_t* strWindowsTitleInUpperCase) +{ + if(strWindowsTitleInUpperCase) + { + EnterCS(); + int i = NUMBER_OF_ALLOWED_WINDOW_TITLES; + lstrcpyn(ALLOWED_WINDOW_TITLES[i], strWindowsTitleInUpperCase, MAX_PATH - 1); + NUMBER_OF_ALLOWED_WINDOW_TITLES = i + 1; + LeaveCS(); + + log(LOGGING_DEBUG, L"Allowing Window %s", strWindowsTitleInUpperCase); + } +} +////////////////////////////////////////////////////////////////////// +// Func: IsAllowedWindowsTitle() +// Desc: Find Allowed Window Title +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::IsAllowedWindowsTitle(wchar_t* strWindowsTitleInUpperCase) +{ + BOOL bRetVal = FALSE; + if(strWindowsTitleInUpperCase) + { + EnterCS(); + for (UINT i = 0; i < NUMBER_OF_ALLOWED_WINDOW_TITLES; ++i) + { + if(wcsstr(strWindowsTitleInUpperCase, ALLOWED_WINDOW_TITLES[i])) + { + bRetVal = TRUE; + break; + } + } + LeaveCS(); + } + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: AddAllowedWindowsClass() +// Desc: Add Allowed Windows Class +////////////////////////////////////////////////////////////////////// +void CWHPaccess::AddAllowedWindowsClass(wchar_t* strWindowsClassInUpperCase) +{ + if(strWindowsClassInUpperCase) + { + EnterCS(); + int i = NUMBER_OF_ALLOWED_WINDOW_CLASSES; + lstrcpyn(ALLOWED_WINDOW_CLASSES[i], strWindowsClassInUpperCase, MAX_PATH - 1); + NUMBER_OF_ALLOWED_WINDOW_CLASSES = i + 1; + LeaveCS(); + + log(LOGGING_DEBUG, L"Allowing Window Class %s", strWindowsClassInUpperCase); + } +} +////////////////////////////////////////////////////////////////////// +// Func: IsAllowedWindowsClass() +// Desc: Find Allowed Window Class +////////////////////////////////////////////////////////////////////// +BOOL CWHPaccess::IsAllowedWindowsClass(wchar_t* strWindowsClassInUpperCase) +{ + BOOL bRetVal = FALSE; + if(strWindowsClassInUpperCase) + { + EnterCS(); + for (UINT i = 0; i < NUMBER_OF_ALLOWED_WINDOW_CLASSES; ++i) + { + if(wcsstr(strWindowsClassInUpperCase, ALLOWED_WINDOW_CLASSES[i])) + { + bRetVal = TRUE; + break; + } + } + LeaveCS(); + } + return bRetVal; +} +////////////////////////////////////////////////////////////////////// +// Func: SetLoggingDetail() +// Desc: Allows us to set a global used by all button hooks to log +////////////////////////////////////////////////////////////////////// +void CWHPaccess::SetLoggingDetail(LoggingDetail nLoggingDetailSetting) +{ + EnterCS(); + nLoggingDetail = nLoggingDetailSetting; + LeaveCS(); +} +////////////////////////////////////////////////////////////////////// +// Desc: Returns the Detail of our Logging (high, medium, low, or none) +////////////////////////////////////////////////////////////////////// +LoggingDetail CWHPaccess::GetLoggingDetail() +{ + return (static_cast(nLoggingDetail)); +} +////////////////////////////////////////////////////////////////////// +// Desc: Get Directory location where we should log to +////////////////////////////////////////////////////////////////////// +wchar_t* CWHPaccess::GetLogPath() +{ + return reinterpret_cast(&LoggingPath); +} +////////////////////////////////////////////////////////////////////// +// Desc: Set Directory location where we should log to +////////////////////////////////////////////////////////////////////// +void CWHPaccess::SetLogPath(wchar_t* buf) +{ + EnterCS(); + lstrcpyn(LoggingPath,buf,MAX_PATH - 1); + EnterCS(); +} \ No newline at end of file diff --git a/Hooks/ButtonHook/CWHPaccess.h b/Hooks/ButtonHook/CWHPaccess.h new file mode 100644 index 0000000..1d70f59 --- /dev/null +++ b/Hooks/ButtonHook/CWHPaccess.h @@ -0,0 +1,97 @@ +// CWHPaccess.h +#pragma once +#include "WPFCaller.h" + +namespace Ooganizer +{ + ////////////////////////////////////////////////////////////////////// + //******************************************************************** + // DS access Class - Created to easily enforce critical sections and + // share the statically created DS + //******************************************************************** + ////////////////////////////////////////////////////////////////////// + class CWHPaccess + { + public: + //// + // All these statics are put into the DS and shared accross all DLL instances + // ~Use accessor functions below to modify these + //// + static HINSTANCE hModule; + static HHOOK hHook; + static HookWndItem HList[MAX_PATH]; + static UINT HListI; + + static wchar_t ALLOWED_PROCESS_NAMES[MAX_PATH][MAX_PATH]; + static UINT NUMBER_OF_ALLOWED_PROCESS_NAMES; + + static wchar_t ALLOWED_WINDOW_TITLES[MAX_PATH][MAX_PATH]; + static UINT NUMBER_OF_ALLOWED_WINDOW_TITLES; + + static wchar_t ALLOWED_WINDOW_CLASSES[MAX_PATH][MAX_PATH]; + static UINT NUMBER_OF_ALLOWED_WINDOW_CLASSES; + + static UINT nLoggingDetail; + static wchar_t LoggingPath[MAX_PATH]; + + // Hook Handle + void set_hHook(HHOOK); + HHOOK get_hHook(); + + // Clears all Shared DS segment's Hook List data + // (imp, when releasing the hook) + void ClearHookSData(); + + // Allows a Caller to get a copy of all hooked Window Handles + // and size of the hooked window list + void GetHookedWindowListNSize(int* nbuf, int* nsize); + + //// + // Find,Insert,Deletion of HookWnd + //// + BOOL InsertHookedWndItem(HookWndItem& Item); + BOOL FindHookedWnd(HWND hWnd); + HookWndItem GetHookedWndItem(HWND hWnd); + BOOL SetHookedWndItem(HWND hWnd, HookWndItem& Item); + BOOL DeleteHookedWnd(HWND hWnd); + + //// + // Allowed ProcessNames & WindowTitles & Classes WhiteList + //// + void AddAllowedProcessName(wchar_t* strProcessNameInUpperCase); + BOOL IsAllowedProcessName(wchar_t* strProcessNameInUpperCase); + void AddAllowedWindowsTitle(wchar_t* strWindowsTitleInUpperCase); + BOOL IsAllowedWindowsTitle(wchar_t* strWindowsTitleInUpperCase); + void AddAllowedWindowsClass(wchar_t* strWindowsClassInUpperCase); + BOOL IsAllowedWindowsClass(wchar_t* strWindowsClassInUpperCase); + + //// + // Get/Set and use Logging Detail Levels + //// + void SetLoggingDetail(LoggingDetail nLoggingDetailSetting); + LoggingDetail GetLoggingDetail(); + wchar_t* GetLogPath(); + void SetLogPath(wchar_t* buf); + + // CRITICAL_SECTION + void EnterCS(); + void LeaveCS(); + + CWHPaccess(); + ~CWHPaccess(); + + private: + //// + // Private functions to keep track of iteration + //// + void deltaListTopI(int); + + //// + // Private Helper Functions + //// + void ClearHookItem(UINT nItem); + + //Many threads could update the DS. + CRITICAL_SECTION cs; + }; +} \ No newline at end of file diff --git a/Hooks/ButtonHook/HookList.h b/Hooks/ButtonHook/HookList.h new file mode 100644 index 0000000..1ecc834 --- /dev/null +++ b/Hooks/ButtonHook/HookList.h @@ -0,0 +1,151 @@ +//#pragma once +// +//#include "malloc.h" +// +//namespace Ooganizer +//{ +// +// enum ButtonState{BUTTON_UP,BUTTON_DOWN}; +// +// ////////////////////////////////////////////////////////////////////// +// // Clss: HookItem +// // Desc: Hook Item is used in the HookList. Each HookItem keeps track +// // of all the addresses needed for each hook, as well as the +// // hookstate. +// // +// // Note: Add State Items for a Window as neccessary +// ////////////////////////////////////////////////////////////////////// +// class HookItem +// { +// public: +// HWND m_hWnd; +// WNDPROC m_HookWndProc; +// WNDPROC m_DefWndProc; +// ButtonState m_btnState; +// +// // Constructor +// HookItem(HWND hWnd, WNDPROC hookWndProc, WNDPROC defWndProc): +// m_hWnd(hWnd), +// m_HookWndProc(hookWndProc), +// m_DefWndProc(defWndProc), +// m_btnState(BUTTON_UP) +// { +// } +// }; +// ////////////////////////////////////////////////////////////////////// +// // Clss: HookList +// // Desc: Generic List / Custom written list for the sake of speed. +// // Hook list is made up of individual HookItems. +// // +// // Note: You can use GetNext() to iterate thru all the items in the list. +// // ~adding or removing an item causes GetNext() to start over. +// ////////////////////////////////////////////////////////////////////// +// class HookList +// { +// public: +// ////////////////////////////////////////////////////////////////////// +// // Func: AddItem() +// // Desc: Adds a HookItem to the List +// ////////////////////////////////////////////////////////////////////// +// void AddItem(HookItem* pItem) +// { +// m_NbrItems++; +// +// if ( m_pHookItem == NULL ) +// m_pHookItem = (HookItem*) malloc( m_NbrItems * sizeof( HookItem ) ); +// else +// m_pHookItem = (HookItem*) realloc( m_pHookItem, m_NbrItems * sizeof( HookItem ) ); +// +// log(pItem->m_hWnd,"hase been added"); +// +// memcpy( m_pHookItem+(m_NbrItems-1), pItem, sizeof( HookItem ) ); +// } +// ////////////////////////////////////////////////////////////////////// +// // Func: GetItem() +// // Desc: Get a HookItem from the List +// ////////////////////////////////////////////////////////////////////// +// HookItem* GetItem(HWND hWnd) +// { +// UINT i; +// HookItem * pItem = m_pHookItem; +// for( i=0; im_hWnd!=hWnd; i++, pItem++ ); +// return ( i < m_NbrItems ) ? pItem : NULL; +// } +// ////////////////////////////////////////////////////////////////////// +// // Func: DelItem() +// // Desc: Deletes a HookItem from the List +// ////////////////////////////////////////////////////////////////////// +// void DelItem(HWND hWnd) +// { +// UINT i; +// HookItem * pItem = m_pHookItem; +// for( i =0; im_hWnd!=hWnd; i++, pItem++ ); +// if ( i < m_NbrItems ) +// { +// m_NbrItems--; +// memcpy( pItem, pItem+1, ( m_NbrItems - i ) * sizeof( HookItem ) ); +// m_pHookItem = (HookItem*) realloc( m_pHookItem, m_NbrItems * sizeof( HookItem ) ); +// +// log(pItem->m_hWnd,"hase been deleted"); +// } +// } +// ////////////////////////////////////////////////////////////////////// +// // Func: DelAllItems() +// // Desc: Deletes all HookItems from the List +// ////////////////////////////////////////////////////////////////////// +// void DelAllItems() +// { +// if ( m_pHookItem != NULL ) +// free( m_pHookItem ); +// m_pHookItem = NULL; +// m_NbrItems = 0; +// } +// ////////////////////////////////////////////////////////////////////// +// // Func: UnhookAllItems() +// // Desc: Responsible for iterating through entire list and 'unhooking' +// // the WndProc function of every HookItem +// // +// // Note: has to be put in here since the list has to be iterated here +// ////////////////////////////////////////////////////////////////////// +// void UnhookAllItems() +// { +// HookItem * pItem; +// +// while ( m_NbrItems > 0 ) +// { +// pItem = m_pHookItem+(m_NbrItems-1); +// +// // Unhook window +// HWND hWnd = pItem->m_hWnd; +// +// log(hWnd,"Unhooking..."); +// SetWindowLong( hWnd, GWL_WNDPROC, (LONG) pItem->m_DefWndProc ); +// SendMessage( hWnd, WM_NCPAINT, 1, 0 ); +// log(hWnd,"Sending WM_NCPAINT message..."); +// +// // Delete item +// DelItem( hWnd ); +// } +// } +// ////////////////////////////////////////////////////////////////////// +// // Func: CleanUp() +// // Desc: Unhooks all HookItems in the list and deletes the list +// ////////////////////////////////////////////////////////////////////// +// void CleanUp() +// { +// UnhookAllItems(); +// DelAllItems(); +// } +// ////////////////////////////////////////////////////////////////////// +// //******************************************************************** +// // Construction / Destruction +// //******************************************************************** +// ////////////////////////////////////////////////////////////////////// +// HookList():m_NbrItems(0),m_pHookItem(NULL){} +// ~HookList(){CleanUp();} +// +// protected: +// UINT m_NbrItems; +// HookItem* m_pHookItem; +// }; +//} \ No newline at end of file diff --git a/Hooks/ButtonHook/HookWndItem.h b/Hooks/ButtonHook/HookWndItem.h new file mode 100644 index 0000000..71cf895 --- /dev/null +++ b/Hooks/ButtonHook/HookWndItem.h @@ -0,0 +1,20 @@ +// HookWndItem.h +#pragma once +extern class CaptionButton; + +////////////////////////////////////////////////////////////////////// +// Strc: HookWndItem +// Desc: Hook Item is used in the HookedWndList. Each HookWndItem keeps track +// of all the addresses needed for each hook for each Windows, +// as well as each Window's ButtonState. +// +// Note: Add State Items for a Window as neccessary +////////////////////////////////////////////////////////////////////// +struct HookWndItem +{ + HWND hWnd; + WNDPROC HookWndProc; + WNDPROC DefWndProc; + ButtonState state; + CaptionButton* button; +}; \ No newline at end of file diff --git a/Hooks/ButtonHook/Stdafx.cpp b/Hooks/ButtonHook/Stdafx.cpp new file mode 100644 index 0000000..ca1c0cb --- /dev/null +++ b/Hooks/ButtonHook/Stdafx.cpp @@ -0,0 +1,153 @@ +// stdafx.cpp : source file that includes just the standard includes +// Ooganizer-Hook.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information +#include "stdafx.h" +#include "stdio.h" +#include "stdlib.h" + +////////////////////////////////////////////////////////////////////// +// Func: SetLoggingDetail() +////////////////////////////////////////////////////////////////////// +void SetLoggingDetail(LoggingDetail detail, wchar_t* logPath) +{ +#ifdef _DEBUG + g_LoggingDetail = LOGGING_DEBUG; +#else + g_LoggingDetail = detail; +#endif + + // If the log path is set externally set it here internally + // else set the log path to %USERPROFILE%\AppData\Local\Temp + if(logPath && logPath[0] != 0) + { + lstrcpyn(g_LogPath, logPath, (MAX_PATH - lstrlen(g_LOG_FILE_NAME))); + } + else + { + size_t len = 0; + errno_t err = 0; + wchar_t* pValue = NULL; + + if(err = _wdupenv_s( &pValue, &len, L"TMP")) + if(err = _wdupenv_s( &pValue, &len, L"TEMP")) + return; + + if(pValue != NULL) + lstrcpyn(g_LogPath, pValue, (MAX_PATH - lstrlen(g_LOG_FILE_NAME))); + } + + // Make sure Path ends with '\' + if(g_LogPath[lstrlen(g_LogPath) - 1] != L'\\') + lstrcat(g_LogPath, L"\\"); + + // Add the Log File name to the path variable (now we have everything) + // ~we are ready to do some serious logging + lstrcat(g_LogPath,g_LOG_FILE_NAME); +} +////////////////////////////////////////////////////////////////////// +// Func: GetLoggingDetail() +////////////////////////////////////////////////////////////////////// +_LoggingDetail GetLoggingDetail() +{ + return g_LoggingDetail; +} +////////////////////////////////////////////////////////////////////// +// Func: log() +// Desc: Logs to Ooganizer.log in defined LogPath or temporary folder +// Prms: Variable # of params +// +// Usge: Log("%s %d %d %d", "test", 1, 2, 3) +////////////////////////////////////////////////////////////////////// +//void log( LoggingDetail detail, char * pFmt, ... ) +//{ +// if(g_LoggingDetail >= detail) +// { +// FILE* pFile = NULL; +// errno_t err = 0; +// +// if ( !( err = fopen_s( &pFile, g_LogPath, "at" ) ) ) +// { +// fprintf( pFile, "ThreadId %i -", GetCurrentThreadId()); +// va_list arg; +// va_start( arg, pFmt ); +// vfprintf( pFile, pFmt, arg ); +// va_end( arg ); +// +// if ( pFmt[strlen( pFmt ) - 1] != '\n' ) +// fprintf( pFile, "\n" ); +// fclose( pFile ); +// } +// } +//} +////////////////////////////////////////////////////////////////////// +// Func: log() +// Desc: Logs to Ooganizer.log in defined LogPath or temporary folder using Wide Char +// Prms: Variable # of params +// +// Usge: Log("%s %d %d %d", "test", 1, 2, 3) +////////////////////////////////////////////////////////////////////// +void log( LoggingDetail detail, wchar_t * pFmt, ... ) +{ + if(g_LoggingDetail >= detail) + { + FILE* pFile = NULL; + errno_t err = 0; + + if ( !( err = _wfopen_s( &pFile, g_LogPath, L"at" ) ) ) + { + + if(detail == LOGGING_LOW) + fwprintf( pFile, L"ThreadId %i - [Imp] - ", GetCurrentThreadId()); // low == very important messages + else if(detail == LOGGING_MEDIUM) + fwprintf( pFile, L"ThreadId %i - {P/D} - ", GetCurrentThreadId()); // medium == program details + else if(detail == LOGGING_HIGH) + fwprintf( pFile, L"ThreadId %i - {X/D} - ", GetCurrentThreadId()); // high == more program details (extra} + else if(detail == LOGGING_DEBUG) + fwprintf( pFile, L"ThreadId %i - Debug - ", GetCurrentThreadId()); // debug == only show up in debug builds (Debug Only) + else + fwprintf( pFile, L"ThreadId %i - - ", GetCurrentThreadId()); // should never happen + + va_list arg; + va_start( arg, pFmt ); + vfwprintf( pFile, pFmt, arg ); + va_end( arg ); + + if ( pFmt[lstrlen( pFmt ) - 1] != '\n' ) + fwprintf( pFile, L"\n" ); + fclose( pFile ); + } + } +} +////////////////////////////////////////////////////////////////////// +// Func: log() +// Desc: Logs the window title text to the Log File +// Prms: HWND, handle to a window +// str, custom string to log +// +// Note: GetWindowText doesn't always return TRUE, if this function +// gets called during the WndProc it will return False +////////////////////////////////////////////////////////////////////// +void log(LoggingDetail detail, HWND hWnd, wchar_t* str) +{ + if(g_LoggingDetail >= detail) + { + wchar_t Title[MAX_PATH + 1] = {0}; + if (GetWindowText(hWnd,Title,MAX_PATH)) + log(detail, L"Window - %s - %s", Title, str); + } +} +////////////////////////////////////////////////////////////////////// +// Func: clearLog() +// Desc: clears the log file (used at startup) - Only Clears if Logging is enabled +////////////////////////////////////////////////////////////////////// +void clearLog() +{ + if(g_LoggingDetail != LOGGING_NONE) + { + FILE* pFile = NULL; + errno_t err = 0; + + if( !( err = _wfopen_s( &pFile, g_LogPath, L"w" ) ) ) + fclose( pFile ); + } +} \ No newline at end of file diff --git a/Hooks/ButtonHook/Stdafx.h b/Hooks/ButtonHook/Stdafx.h new file mode 100644 index 0000000..312dd01 --- /dev/null +++ b/Hooks/ButtonHook/Stdafx.h @@ -0,0 +1,47 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently +#pragma once + +// Compiler Error Messages that we want to disable: +#pragma warning ( disable : 4793 ) // Compiling functions as native code +#pragma warning ( disable : 4996 ) // 'strncpy': This function or variable may be unsafe + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include + +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Global Enums +//******************************************************************** +////////////////////////////////////////////////////////////////////// + +// Logging Detail Settings +typedef enum _LoggingDetail{LOGGING_NONE,LOGGING_LOW,LOGGING_MEDIUM,LOGGING_HIGH,LOGGING_DEBUG} LoggingDetail; + +// Enable Logging and if so, which detail (default = none) +static LoggingDetail g_LoggingDetail = LOGGING_NONE; +static wchar_t g_LogPath[MAX_PATH + 1] = {0}; +static const wchar_t g_LOG_FILE_NAME[] = L"ButtonHook.log"; // Log File for now is just hardcoded + +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Global Functions +//******************************************************************** +////////////////////////////////////////////////////////////////////// + +// Logs to Ooganizer.log in temporary folder if no log path is set +// %USERPROFILE%\AppData\Local\Temp\Ooganizer.log +//void log(LoggingDetail detail, char * pFmt, ... ); +void log( LoggingDetail detail, HWND hWnd, wchar_t* str); // Logs Window Text +void log( LoggingDetail detail, wchar_t * pFmt, ... ); + +// At Startup we clear the log +void clearLog(); + +// Set the global (for this dll instance) Logging Detail Setting +void SetLoggingDetail(LoggingDetail detail, wchar_t* logPath); + +// Get Logging Detail for custom debug behavior +_LoggingDetail GetLoggingDetail(); \ No newline at end of file diff --git a/Hooks/ButtonHook/WPFCaller.cpp b/Hooks/ButtonHook/WPFCaller.cpp new file mode 100644 index 0000000..334f1f1 --- /dev/null +++ b/Hooks/ButtonHook/WPFCaller.cpp @@ -0,0 +1,1417 @@ +#include "StdAfx.h" +#include "WPFCaller.h" +#include "CWHPaccess.h" +#include "shellapi.h" +#include "dde.h" +#include "ddeml.h" + +using namespace Ooganizer; + +// Specifies a nonzero timer identifier +#define NID_RESTORE_EVENT_TIMER (WM_USER + 1) +#define NID_CLOSE_BUT_NOT_DESTROY_EVENT_TIMER (WM_USER + 2) + +// * Messages send from WPFCaller class to WPFProc Thread +#define WM_KILLTHREAD (WM_USER + 501) + +// * Messages Send from W32Button to WPFProc Thread +#define WM_GETBUTTONTHEMESETTING (WM_USER + 601) +#define WM_W32BUTTONCLICKED (WM_USER + 602) + +// * External Messages * Send to us by outside +// Programs (most likely WPFForm or Platform) +#define WM_W32PINGISALIVE (WM_USER + 700) +#define WM_W32SETBUTTONSTATE (WM_USER + 701) +#define WM_W32GETBUTTONSTATE (WM_USER + 702) +#define WM_W32SETPARENTWINDOWTRANSPERANCY (WM_USER + 703) +#define WM_W32SETPARENTWINDOWACTIVE (WM_USER + 704) +#define WM_W32POSTMESSAGETOPARENTWINDOW (WM_USER + 705) + +// * Messages Only handled by WPFThreadProc * Events Send to +// C# Client Event Dispatcher for handling +#define WM_CLIENT_EVENT_WINDOWACTIVATE (WM_USER + 800) +#define WM_CLIENT_EVENT_DRAGNDROPOCCURED (WM_USER + 801) +#define WM_CLIENT_EVENT_MDICHILDWINDOWSWITCHOCCURED (WM_USER + 802) +#define WM_CLIENT_EVENT_PARENTGETSETTEXTOCCURED (WM_USER + 803) +#define WM_CLIENT_EVENT_PARENTNOTIFYLBUTTONCLICKOCCURED (WM_USER + 804) +#define WM_CLIENT_EVENT_PARENTNOTIFYWMCREATEOCCURED (WM_USER + 805) +#define WM_CLIENT_EVENT_PARENTCLOSEWITHOUTDESTROYOCCURED (WM_USER + 806) +#define WM_CLIENT_EVENT_PARENTSETFOCUSOCCURED (WM_USER + 807) +#define WM_CLIENT_EVENT_OPENFILEORSAVEASDIALOGOCCURED (WM_USER + 808) + +#ifdef _DEBUG + #import "..\\..\\Target\\Debug\\Settings.tlb" raw_interfaces_only +#else + #import "..\\..\\Target\\Release\\Settings.tlb" raw_interfaces_only +#endif +using namespace Settings; + +// access the SharedDS *initialized by WPFCaller() constructor* +CWHPaccess* s_WPFCallerAccess = NULL; + +////////////////////////////////////////////////////////////////////// +// Func: ReadButtonThemeSetting +// Desc: static function to quickly read in Button Theme Settings. +// ~Uses COM, must be called ONLY from within a COM initialized Thread! +////////////////////////////////////////////////////////////////////// +bool ReadButtonThemeSetting(WPFCaller* pCaller) +{ + HRESULT hr = S_FALSE; + + _ButtonThemeNIconSettingsCCWPtr pButtonThemeNIconSetting; + hr = pButtonThemeNIconSetting.CreateInstance(__uuidof(ButtonThemeNIconSettingsCCW)); + + if(SUCCEEDED(hr)) + { + log(LOGGING_HIGH, L"Succeed creating ButtonThemeNIconSettings Instance"); + } + else + { + log(LOGGING_LOW, L"FAILED to create the ButtonThemeNIconSettings COM Instance"); + return false; + } + + //// + // Get the Button Theme N Icon Settings + //// + IButtonThemeSettingPtr pThemeSetting; + IButtonIconLocationPtr pIconLocation; + pButtonThemeNIconSetting->GetIButtonThemeInterface(&pThemeSetting); + pButtonThemeNIconSetting->GetIButtonIconLocation(&pIconLocation); + + if(pThemeSetting == NULL) + log(LOGGING_LOW, L"pThemeSetting == NULL - Error"); + if(pIconLocation == NULL) + log(LOGGING_LOW, L"pIconLocation == NULL - Error"); + + if((pThemeSetting == NULL) || (pIconLocation == NULL)) + return false; + + //// + // Get Button Dimension/Location + //// + if(SUCCEEDED(hr)) + hr = pThemeSetting->Top(&pCaller->m_ButtonThemeSetting.Top); + if(SUCCEEDED(hr)) + hr = pThemeSetting->Right(&pCaller->m_ButtonThemeSetting.Right); + if(SUCCEEDED(hr)) + hr = pThemeSetting->Height(&pCaller->m_ButtonThemeSetting.Height); + if(SUCCEEDED(hr)) + hr = pThemeSetting->Width(&pCaller->m_ButtonThemeSetting.Width); + + //// + // Get Button Icon Location + //// + if(SUCCEEDED(hr)) + pIconLocation->GetBUTTON_UP(pCaller->m_ButtonThemeSetting.bstrBUTTON_UP.GetAddress()); + if(SUCCEEDED(hr)) + pIconLocation->GetBUTTON_DOWN(pCaller->m_ButtonThemeSetting.bstrBUTTON_DOWN.GetAddress()); + if(SUCCEEDED(hr)) + pIconLocation->GetTOGGLE_UP(pCaller->m_ButtonThemeSetting.bstrTOGGLE_UP.GetAddress()); + + if(SUCCEEDED(hr)) + { + log(LOGGING_HIGH, L"ReadButtonTheme Settings Successfully - Height=%i, Width=%i, Top=%i, Right=%i", + pCaller->m_ButtonThemeSetting.Height,pCaller->m_ButtonThemeSetting.Width,pCaller->m_ButtonThemeSetting.Top, pCaller->m_ButtonThemeSetting.Right); + + if(pCaller->m_ButtonThemeSetting.bIsInitialized) + pCaller->m_ButtonThemeSetting.bIsChanged = true; + + if(!pCaller->m_ButtonThemeSetting.bIsInitialized) + pCaller->m_ButtonThemeSetting.bIsInitialized = true; + } + else + { + pCaller->m_ButtonThemeSetting.bIsChanged = false; + pCaller->m_ButtonThemeSetting.bIsInitialized = false; + log(LOGGING_LOW, L"ReadButtonTheme Settings FAILED!"); + } + + if(SUCCEEDED(hr)) + return true; + else + return false; +} + +//// +// When we want to communicate back to the ButtonHook from externaly windows, +// we use these custom messages in order to do so. We keep track of them seperatly +// because we allow Custom Messages to return a Value to the caller. +//// +UINT s_nMessagesCustomMessages = 6; +UINT s_nMessagesCustomMessagesWeHave[] = +{ + WM_W32PINGISALIVE, + WM_W32SETBUTTONSTATE, + WM_W32GETBUTTONSTATE, + WM_W32SETPARENTWINDOWTRANSPERANCY, + WM_W32SETPARENTWINDOWACTIVE, + WM_W32POSTMESSAGETOPARENTWINDOW +}; +bool g_IsMessageACustomMessage(UINT msgID) +{ + for(UINT i = 0; i < s_nMessagesCustomMessages; ++i) + { + if(s_nMessagesCustomMessagesWeHave[i] == msgID) + return true; + } + return false; +} +//// +// For wndproc to know what we care about and pass it down to to W32WndProc +// ~these messages will be tagged with WM_USER for us to handle in our W32WndProc +//// +UINT s_nMessagesWPFormCaresAbout = 2; +UINT s_MessagesWPFormCaresAbout[] = +{ + WM_ACTIVATE, + WM_SIZE, +}; +bool g_IsMessageWPFormCaresAbout(UINT msgID) +{ + for(UINT i = 0; i < s_nMessagesWPFormCaresAbout; ++i) + { + if(s_MessagesWPFormCaresAbout[i] == msgID) + return true; + } + return false; +} +//// +// For wndproc to know what we care about and pass it down to to MainWndProc +// ~these messages will be send straight down for us to handle in our MainWndProc +//// +UINT s_nMessagesW32WindowCaresAbout = 8; +UINT s_MessagesW32WindowCaresAbout[] = +{ + WM_PAINT, + WM_DISPLAYCHANGE, + WM_THEMECHANGED, + WM_SIZE, + WM_MOVE, + WM_LBUTTONDOWN, + WM_MOUSEMOVE, + WM_SHOWWINDOW +}; +bool g_IsMessageW32WindowCaresAbout(UINT msgID) +{ + for(UINT i = 0; i < s_nMessagesW32WindowCaresAbout; ++i) + { + if(s_MessagesW32WindowCaresAbout[i] == msgID) + return true; + } + return false; +} +////////////////////////////////////////////////////////////////////// +// Desc: We need to make sure that we have the init button settings, +// before we can continue in many of our Messaging functions +////////////////////////////////////////////////////////////////////// +void MakeSureButtonThemeSettingWereInitialized(WPFCaller* pCaller) +{ + // We must make sure the Button has all the settings before + // we can draw,move it, etc so sleep the thread until we know we have them + while(!pCaller->m_ButtonThemeSetting.bIsInitialized) + Sleep(20); +} +////////////////////////////////////////////////////////////////////// +// Desc: For our WPFThread callback into WPForm we must make sure +// that we have the handle for our W32Button so to pass it down to them +////////////////////////////////////////////////////////////////////// +void MakeSureW32ButtonWindowGotCreated(WPFCaller* pCaller) +{ + // We must make sure the Button window got created so we can pass the + // handle down + while(pCaller->m_hwndW32Window == NULL) + Sleep(20); +} +////////////////////////////////////////////////////////////////////// +// Desc: For our Win32 Thread we must make sure we have a valid pointer to +// a WPFCaller Object. +////////////////////////////////////////////////////////////////////// +WPFCaller* GetWPFCallerObject(HWND ParenthWnd) +{ + if(s_WPFCallerAccess) + { + BLANK_HookWndItem(Item); + Item = s_WPFCallerAccess->GetHookedWndItem(ParenthWnd); + WPFCaller* pCaller = Item.wpfcaller; + return pCaller; + } + return NULL; +} +////////////////////////////////////////////////////////////////////// +// Func: DrawIconButton (Owner Drawing out Buttons) +// Desc: Responsible for drawing the owner buttons onto the caption bar +////////////////////////////////////////////////////////////////////// +bool DrawIconButton(HINSTANCE hInstance,HDC hdc, WPFCaller* pCaller) +{ + // static Icon handles: + static HANDLE hCurrIcon = NULL; + static HANDLE hButtonUp = NULL; + static HANDLE hButtonDown = NULL; + static HANDLE hToggleUp = NULL; + + // LoadIcon only loads once, but LoadImage does not, + // so in case you call the latter, use this flag + static bool bIconsLoaded = false; + + // Make sure that we don't continue unless we have all the settings + MakeSureButtonThemeSettingWereInitialized(pCaller); + + if (!bIconsLoaded || pCaller->m_ButtonThemeSetting.bIsChanged) + { + //// + // ButtonUp + //// + if(!hButtonUp) + { + HANDLE hTemp = hButtonUp; + hButtonUp = NULL; //*avoid poss. threading issue + DestroyIcon((HICON)hTemp); + } + hButtonUp = LoadImage(hInstance, (WCHAR*)pCaller->m_ButtonThemeSetting.bstrBUTTON_UP,IMAGE_ICON,pCaller->m_ButtonThemeSetting.Width,pCaller->m_ButtonThemeSetting.Height,LR_LOADFROMFILE); + if(!hButtonUp) + log(LOGGING_LOW, L"hButtonUp LoadImage Failed! with error %i - path %s",GetLastError(),(wchar_t*)pCaller->m_ButtonThemeSetting.bstrBUTTON_UP); + + //// + // ButtonDown + //// + if(!hButtonDown) + { + HANDLE hTemp = hButtonDown; + hButtonDown = NULL; //*avoid poss. threading issue + DestroyIcon((HICON)hTemp); + } + hButtonDown = LoadImage(hInstance, (WCHAR*)pCaller->m_ButtonThemeSetting.bstrBUTTON_DOWN,IMAGE_ICON,pCaller->m_ButtonThemeSetting.Width,pCaller->m_ButtonThemeSetting.Height,LR_LOADFROMFILE); + if(!hButtonDown) + log(LOGGING_LOW, L"hButtonDown LoadImage Failed! with error %i - path %s",GetLastError(),(wchar_t*)pCaller->m_ButtonThemeSetting.bstrBUTTON_DOWN); + + //// + // ToogleUp + //// + if(!hToggleUp) + { + HANDLE hTemp = hToggleUp; + hToggleUp = NULL; //*avoid poss. threading issue + DestroyIcon((HICON)hTemp); + } + hToggleUp = LoadImage(hInstance, (WCHAR*)pCaller->m_ButtonThemeSetting.bstrTOGGLE_UP,IMAGE_ICON,pCaller->m_ButtonThemeSetting.Width,pCaller->m_ButtonThemeSetting.Height,LR_LOADFROMFILE); + if(!hToggleUp) + log(LOGGING_LOW, L"hToggleUp LoadImage Failed! with error %i - path %s",GetLastError(),(wchar_t*)pCaller->m_ButtonThemeSetting.bstrTOGGLE_UP); + + // Everything went well. + bIconsLoaded = true; + pCaller->m_ButtonThemeSetting.bIsChanged = false; + } + + //// + // Now Draw the proper Icon State + //// + bool bUseToogleState = (pCaller->m_ButtonToggledState != BUTTON_NONE); + + if(!bUseToogleState && pCaller->m_ButtonState == BUTTON_DOWN) + hCurrIcon = hButtonDown; + else if(pCaller->m_ButtonState == BUTTON_UP) + hCurrIcon = hButtonUp; + else if(bUseToogleState || pCaller->m_ButtonState == BUTTON_TOGGLED) + hCurrIcon = hToggleUp; + + if(hCurrIcon != NULL) + { + if (!DrawIconEx(hdc,0,0,(HICON) hCurrIcon, + pCaller->m_ButtonThemeSetting.Width, + pCaller->m_ButtonThemeSetting.Height, + 0, NULL, DI_NORMAL)) + { + log(LOGGING_LOW, L"DrawIconEx Failed!"); + return false; + } + } + + return true; +} +////////////////////////////////////////////////////////////////////// +// Desc: Set static HeightNWidth (keeping track of the Window size) +////////////////////////////////////////////////////////////////////// +void Helper_GetRectAndSetHeightNWidth(HWND hWnd, WPFCaller* pCaller) +{ + RECT rect; + GetWindowRect(hWnd,&rect); + + pCaller->m_wndHeight = (rect.bottom - rect.top); + pCaller->m_wndWidth = (rect.right - rect.left); + pCaller->m_wndRECT = rect; +} +////////////////////////////////////////////////////////////////////// +// Desc: Set static HeightNWidth (keeping track of the Window size) +////////////////////////////////////////////////////////////////////// +void Helper_GetRectAndSetHeightNWidthUsingPlacement(HWND hWnd, WPFCaller* pCaller) +{ + WINDOWPLACEMENT place; + place.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hWnd,&place); + + pCaller->m_wndHeight = (place.rcNormalPosition.bottom - place.rcNormalPosition.top); + pCaller->m_wndWidth = (place.rcNormalPosition.right - place.rcNormalPosition.left); + pCaller->m_wndRECT = place.rcNormalPosition; +} +////////////////////////////////////////////////////////////////////// +// Func: W32WndProc (W32Window) +// Desc: Responsible for handling the Wnd32Window's incoming messages +////////////////////////////////////////////////////////////////////// +LRESULT CALLBACK W32WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + PAINTSTRUCT ps; + HDC hdc; + int nTop = 0; + int nRight = 0; + bool bIsMaximized = false; + HINSTANCE hInst = NULL; + + // Use the ParentHWND to get access to the correct WPFCaller instance, + // we need to do this in case multiple windows exist in the same process + WPFCaller* pCaller = GetWPFCallerObject(::GetParent(hWnd)); + + // Nothing to do here, WPFCaller is not ready (just handle the message) + if(pCaller == NULL) + goto HANDLE_MESSAGE; + + //// + // Messages should be handled here (if we are interested) + //// + try + { + // For some calls we need th HINSTANCE + hInst = pCaller->m_hInst; + + switch(Msg) + { + //// + // Win32Button Messages we handle + //// + case WM_SIZE: + if(wParam == SIZE_MINIMIZED) + { + pCaller->m_bButtonIsMinimized = true; + } + else if((wParam == SIZE_RESTORED && pCaller->m_bButtonIsMinimized) || + (wParam == SIZE_MAXIMIZED && pCaller->m_bButtonIsMinimized)) + { + // the Button receives this message way before the parent does. + pCaller->m_bButtonIsBeingRestored = true; + } + // Intentional Fallthru + case WM_DISPLAYCHANGE: + case WM_MOVE: + { + // ~Calculate Offset for Maximized Windows - IMP + // in vista, we need 7 height offset + // we need 5 width offset + // ~i tried using the best values that make sense + const int YHEIGHT_OFFSET = GetSystemMetrics(SM_CYFRAME) - 1; // subtract 1 to better position the button (and not cut it off as much) + const int XWIDTH_OFFSET = (2 * GetSystemMetrics(SM_CXEDGE)) + GetSystemMetrics(SM_CXBORDER); + bool bIsMaximized = (IsZoomed(pCaller->m_hWnd) == TRUE); + + int YOFFSET = 0; + int XOFFSET = 0; + if(bIsMaximized) + { + YOFFSET = YHEIGHT_OFFSET; + XOFFSET = XWIDTH_OFFSET; + } + + // Set the Window Position (Use Offset if need be) + MakeSureButtonThemeSettingWereInitialized(pCaller); + Helper_GetRectAndSetHeightNWidth(pCaller->m_hWnd, pCaller); + nTop = pCaller->m_wndRECT.top + pCaller->m_ButtonThemeSetting.Top; + nRight = pCaller->m_wndRECT.left + pCaller->m_wndWidth - pCaller->m_ButtonThemeSetting.Right; + SetWindowPos(hWnd, HWND_TOP, nRight - XOFFSET, nTop + YOFFSET, pCaller->m_ButtonThemeSetting.Width, pCaller->m_ButtonThemeSetting.Height, NULL); + + bool bIsMinimizeMoveMessage = false; + if(Msg == WM_MOVE) + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + bIsMinimizeMoveMessage = (x > 33500) && (y > 33500); + } + // If the window is just too damn small to hold all the buttons just hide it! + // ~better user experience + const int MIN_WITDH_TO_DISPLAY_BUTTON_IN = 300; + if((pCaller->m_wndWidth > 25) && /* make sure width is bigger >0 may as well put in some magic number buffer */ + !bIsMinimizeMoveMessage && + (pCaller->m_wndWidth < MIN_WITDH_TO_DISPLAY_BUTTON_IN) && !pCaller->m_bButtonIsArtificiallyHidden_MOVE && !pCaller->m_bButtonIsMinimized) + { + log(LOGGING_DEBUG, L"WM_MOVE Setting ButtonWindow Artificially Hidden to true"); + pCaller->m_bButtonIsArtificiallyHidden_MOVE = true; + RedrawWindow(pCaller->m_hwndW32Window,NULL,NULL,(RDW_INVALIDATE | RDW_UPDATENOW)); + } + else if((pCaller->m_wndWidth >= MIN_WITDH_TO_DISPLAY_BUTTON_IN) && pCaller->m_bButtonIsArtificiallyHidden_MOVE && !pCaller->m_bButtonIsMinimized) + { + log(LOGGING_DEBUG, L"WM_MOVE Setting ButtonWindow Artificially Hidden to false"); + pCaller->m_bButtonIsArtificiallyHidden_MOVE = false; + pCaller->StartRestoreEventFadeTimer(); + } + return 0; + } + break; + + case WM_SHOWWINDOW: + if((BOOL) wParam == FALSE) // window is being hidden + { + pCaller->SetAlpha(0); + } + else if((BOOL) wParam == TRUE) // window is being shown + { + pCaller->StartRestoreEventFadeTimer(); + } + return 0; + + case WM_MOUSEMOVE: + TRACKMOUSEEVENT mouseEvent; + mouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + mouseEvent.dwFlags = TME_HOVER | TME_LEAVE; + mouseEvent.hwndTrack = hWnd; + mouseEvent.dwHoverTime = 25; + TrackMouseEvent(&mouseEvent); + break; + + case WM_LBUTTONDOWN: + log(LOGGING_HIGH, L"ButtonWindow received ButtonClick Sending Click Event to WPForm"); + PostThreadMessage(pCaller->m_threadID,WM_W32BUTTONCLICKED,NULL,NULL); + return 0; + + case WM_MOUSEHOVER: + pCaller->m_ButtonState = BUTTON_UP; + RedrawWindow(pCaller->m_hwndW32Window,NULL,NULL,(RDW_INVALIDATE | RDW_UPDATENOW)); + return 0; + + case WM_MOUSELEAVE: + pCaller->m_ButtonState = BUTTON_DOWN; + RedrawWindow(pCaller->m_hwndW32Window,NULL,NULL,(RDW_INVALIDATE | RDW_UPDATENOW)); + return 0; + + case WM_TIMER: + // FadeInTimer (Restore from Minimize) + if(wParam == NID_RESTORE_EVENT_TIMER) + { + // Increment Opaqueness + const int SLEEP_INCREMENT = 1; // 1 == lowest + const int LOWER_INCREMENT = 7; + const int MIDDLE_INCREMENT = 15; + const int UPPER_INCREMENT = 25; + + // Increment Points + const int SLEEP_DONE_POINT = 7; // (7 + 1) * 20 = 160ms of sleep + const int LOWER_POINT = 60; + const int MIDDLE_POINT = 160; + const int UPPER_POINT = 230; + + BYTE alpha = pCaller->GetAlpha(); + if(alpha >= UPPER_POINT) + alpha = 255; // just show the thing already + else if(alpha <= SLEEP_DONE_POINT) // sleep a little in the beginning... + alpha += SLEEP_INCREMENT; + else if(alpha <= LOWER_POINT) + alpha += LOWER_INCREMENT; + else if(alpha <= MIDDLE_POINT) + alpha += MIDDLE_INCREMENT; + else + alpha += UPPER_INCREMENT; + + // Set the calculated Alpha Opaqueness + pCaller->SetAlpha(alpha); + + // Close Restore Timer if we are done + if(pCaller->GetAlpha() == 255) + { + // Kill the Restore Timer + KillTimer(hWnd,NID_RESTORE_EVENT_TIMER); + log(LOGGING_DEBUG, L"Stopping Restore Event Timer"); + } + } + else if(wParam == NID_CLOSE_BUT_NOT_DESTROY_EVENT_TIMER) // Closing Timer for MDI Apps (notify WPFCaller) + { + // We'll run this timer 21x, that should give us ~5 seconds (more than enough, i hope in 99% of cases) + if(pCaller->m_StartCloseButNotDestroyTimerCount == 20) + { + log(LOGGING_DEBUG, L"Stopping Close But not Destroy Timer"); + pCaller->m_StartCloseButNotDestroyTimerCount = 0; + KillTimer(hWnd,NID_CLOSE_BUT_NOT_DESTROY_EVENT_TIMER); + } + else + { + log(LOGGING_DEBUG, L"EventDispatcherHandler - WM_CLOSE but no WM_DESTROY Occured letting WPFCaller know"); + pCaller->m_StartCloseButNotDestroyTimerCount = pCaller->m_StartCloseButNotDestroyTimerCount + 1; + PostThreadMessage(pCaller->m_threadID, WM_CLIENT_EVENT_PARENTCLOSEWITHOUTDESTROYOCCURED,0,0); + } + } + break; + + case WM_PAINT: + // If we are minimized and we are getting messages from our parent + // ~now we can launch the restore Timer + if(pCaller->m_bButtonIsBeingRestored && + (wParam == (WPARAM) pCaller->m_hWnd) && (lParam == (LPARAM) pCaller->m_hWnd)) + { + // restore timer will from now on handle the restore + pCaller->m_bButtonIsBeingRestored = false; + pCaller->m_bButtonIsMinimized = false; + + // Hides the Button Completly + log(LOGGING_DEBUG, L"WM_PAINT is starting StartRestoreEventFadeTimer()"); + pCaller->StartRestoreEventFadeTimer(); + } + + // Only Draw the button when we want to + if(!pCaller->m_bButtonIsMinimized && + !pCaller->m_bButtonIsArtificiallyHidden_MOVE) + { + hdc = BeginPaint(hWnd, &ps); + DrawIconButton(hInst,ps.hdc,pCaller); + EndPaint(hWnd, &ps); + } + return 0; + + case WM_THEMECHANGED: + log(LOGGING_MEDIUM, L"Received WM_THEMECHANGED. W32Button is trying to retrieve new Theme Settings via WPFProc"); + PostThreadMessage(pCaller->m_threadID,WM_GETBUTTONTHEMESETTING,NULL,NULL); + break; + + case WM_W32PINGISALIVE: + return 1; + + case WM_W32SETBUTTONSTATE: + log(LOGGING_DEBUG, L"Received WM_W32SetButtonState Message. Setting Button to %d", (int)lParam); + pCaller->m_ButtonState = (BUTTON_STATE) lParam; + + // Button will be toggled / untoggled when the caller set it + if(pCaller->m_ButtonState == BUTTON_TOGGLED) + pCaller->m_ButtonToggledState = BUTTON_TOGGLED; + else + pCaller->m_ButtonToggledState = BUTTON_NONE; + + RedrawWindow(pCaller->m_hwndW32Window,NULL,NULL,(RDW_INVALIDATE | RDW_UPDATENOW)); + return 1; + + case WM_W32GETBUTTONSTATE: + log(LOGGING_DEBUG, L"Received WM_W32GetButtonState Message. Sending Button State %d", (int)pCaller->m_ButtonState); + return (LRESULT) pCaller->m_ButtonState; + + case WM_W32SETPARENTWINDOWTRANSPERANCY: + { + if((int)lParam == 0) + log(LOGGING_DEBUG, L"Received WM_W32SETPARENTWINDOWTRANSPERANCY Message with Alpha Setting of %u - Invisible", (int)lParam); + else if((int)lParam == 255) + log(LOGGING_DEBUG, L"Received WM_W32SETPARENTWINDOWTRANSPERANCY Message with Alpha Setting of %u - Visible", (int)lParam); + + long dwStyle = (GetWindowLong(pCaller->m_hWnd,GWL_EXSTYLE) | WS_EX_LAYERED); + long retVal = SetWindowLong(pCaller->m_hWnd,GWL_EXSTYLE,dwStyle); + + if(retVal == 0) + { + log(LOGGING_LOW, L"WM_W32SETPARENTWINDOWTRANSPERANCY SetWindowLong Failed! It returned 0"); + return 0; + } + + // Set the Alpha Channel on the Parent Window + if(!SetLayeredWindowAttributes(pCaller->m_hWnd,RGB(0,0,0),(BYTE)lParam,LWA_ALPHA)) + { + log(LOGGING_LOW, L"WM_W32SETPARENTWINDOWTRANSPERANCY SetLayeredWindowAttributes Failed! It returned false"); + return 0; + } + + // Also Set it on the Button (let it become transparent/untransparent with the hooked window) + pCaller->SetAlpha((BYTE)lParam); + } + return 1; + + case WM_W32SETPARENTWINDOWACTIVE: + { + HWND hWnd = ::SetActiveWindow(pCaller->m_hWnd); + if(hWnd == NULL) + return 0; + else + return 1; + } + return 0; + + case WM_W32POSTMESSAGETOPARENTWINDOW: + { + if((int)lParam != 0) + { + wchar_t buf[MAX_PATH] = {0}; + if(GlobalGetAtomName((ATOM) lParam, buf,MAX_PATH) == 0) + { + log(LOGGING_DEBUG, L"*Error* - WM_W32SENDMESSAGETOPARENTWINDOW received no String from Atom"); + } + else + { + HWND hWndM = NULL; + UINT MsgM = 0; + WPARAM wParamM = 0; + LPARAM lParamM = 0; + int IntsM[4] = {0}; + + bool bParseFailed = false; + log(LOGGING_DEBUG, L"WM_W32SENDMESSAGETOPARENTWINDOW received String from Atom %s", buf); + + wchar_t* pToken = wcstok(buf, L";"); + for (int i = 0; (pToken != NULL) && (i < 4); ++i) + { + log(LOGGING_DEBUG, L"WM_W32SENDMESSAGETOPARENTWINDOW Token %d - %s", (i + 1), pToken); + IntsM[i] = _wtoi(pToken); + if(((i == 0) || (i == 1))&& (IntsM[i] == 0)) + { + log(LOGGING_DEBUG, L"*Error* - WM_W32SENDMESSAGETOPARENTWINDOW token %d is invalid", (i + 1)); + bParseFailed = true; + } + + pToken = wcstok(NULL, L";"); + } + + if(!bParseFailed) + { + hWndM = (HWND) IntsM[0]; + MsgM = (UINT) IntsM[1]; + wParamM = (WPARAM) IntsM[2]; + lParamM = (LPARAM) IntsM[3]; + + if(IsWindow(hWndM)) + { + log(LOGGING_DEBUG, L"WM_W32SENDMESSAGETOPARENTWINDOW Posting Message to hWnd %d, Msg %d, wParam %d, lParam %i", hWndM, MsgM, wParamM, lParamM); + PostMessage(hWndM,MsgM,wParamM,lParamM); + return 1; + } + else + log(LOGGING_DEBUG, L"*Error* - WM_W32SENDMESSAGETOPARENTWINDOW window handle %d is invalid", hWndM); + } + return 0; + } + } + else + { + log(LOGGING_DEBUG, L"*Error* - WM_W32SENDMESSAGETOPARENTWINDOW received no Atom"); + } + } + return 0; + + } + } + catch(...) + { + log(LOGGING_LOW, L"*Error* - A fatal error occured in W32WndProc for W32Button"); + } + + HANDLE_MESSAGE: + LRESULT lr = DefWindowProc(hWnd,Msg,wParam,lParam); + return (lr); +} +////////////////////////////////////////////////////////////////////// +// Func: WPFThreadProc (WPFButtonForm) +// Desc: Responsible for handling messages that are supposed to go to the WPFButtonForm +////////////////////////////////////////////////////////////////////// +DWORD WINAPI WPFThreadProc(__in LPVOID lpParameter) +{ + CoInitialize(NULL); + MSG msg; + + // Force the system to create a message queue for the thread + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + IButtonFormPtr wpfForm; + IClientEventsPtr EventDispatcherForwarder; + + WPFCaller* pCaller = (WPFCaller*) lpParameter; + + // handle to parent window (Hooked Window) + HWND hWnd = pCaller->m_hWnd; + + // First thing we want to do is read the icon setting for the win32 button + // *we are doing it here because we are reading the settings using COM, + // and this thread is COM enabled + if(!ReadButtonThemeSetting(pCaller)) + return -1; + + // We need to sit here idly and wait to make sure that we got the Button Window Handle + MakeSureW32ButtonWindowGotCreated(pCaller); + HWND hWndButton = pCaller->m_hwndW32Window; // handle to the Button Window + log(LOGGING_DEBUG, L"WPFThreadProc: Wait over. ButtonW32 Window got created (%u).", hWndButton); + + // Try to create a WPF Form Objects + HRESULT hr = wpfForm.CreateInstance(__uuidof(ButtonWPFormCCW)); + + if(SUCCEEDED(hr)) + { + try + { + // Let's get the IClientEvents Interface to forward Window Client Events + log(LOGGING_HIGH, L"Trying to query for IClientEvents Interface"); + HRESULT hr = wpfForm.QueryInterface(__uuidof(IClientEvents), &EventDispatcherForwarder); + + if(SUCCEEDED(hr)) + log(LOGGING_HIGH, L"Querying for IClientEvents succeeded"); + else + log(LOGGING_LOW, L"Querying for IClientEvents failed"); + + // Let the WPF form know that we activated (and pass out the window handle + // that activated it) ~this is importanted for housekeeping. also pass out the + // Button Handle so that it can set it's state. ~Imp + log(LOGGING_DEBUG, L"Calling WPFThreadProc_ButtonWPForm_Activated Method with Parent (%u) and Button (%u)", hWnd, hWndButton); + wpfForm->WPFThreadProc_ButtonWPForm_Activated((long)hWnd, (long) hWndButton); + log(LOGGING_HIGH, L"Calling WPFThreadProc_ButtonWPForm_Activated Method Returned - Everything is O.K."); + + // Also let the Client Event know the same thing + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT hWndInitialActivate() forwarding it to WPFButton for PID %u and hWnd %u with CommandLine %s", ::GetCurrentProcessId(), hWnd, ::GetCommandLine()); + _bstr_t CommandLinePrms(GetCommandLine()); + EventDispatcherForwarder->hWndInitialActivate(GetCurrentProcessId(), (long)hWnd,CommandLinePrms); + log(LOGGING_HIGH, L"WM_CLIENT_EVENT hWndInitialActivate() returned - Everything is O.K."); + + // Let OnDefault know that this Thread is ready to receive messages + pCaller->m_bThreadIsReady = true; + BOOL bRet = FALSE; + + while( (bRet = GetMessage( &msg, (HWND)-1, 0, 0 )) != 0) + { + if (bRet == -1) + { + // handle the error and possibly exit + log(LOGGING_LOW, L"A Fatal Error Occured in ThreadProc. Exiting!", hr); + goto STOPPING_THREAD; + break; + } + else + { + //// + // MAIN MESSAGE LOOP + //// + switch(msg.message) + { + case WM_KILLTHREAD: + log(LOGGING_MEDIUM, L"WM_KILLTHREAD was Posted to Thread. Exiting Window(%u) in pid(%u).", pCaller->m_hWnd, GetCurrentProcessId()); + pCaller->m_hwndWPForm = NULL; + goto STOPPING_THREAD; + break; + + case WM_GETBUTTONTHEMESETTING: + if(ReadButtonThemeSetting(pCaller)) + log(LOGGING_HIGH, L"Received GetButtonThemeSetting Message - Read ButtonThemeSettings Succeeded"); + else + log(LOGGING_LOW, L"Received GetButtonThemeSetting Message - Read ButtonThemeSettings Failed!"); + break; + + case WM_W32BUTTONCLICKED: + log(LOGGING_DEBUG, L"WM_W32BUTTONCLICKED passing down to WPFForm->W32BUTTONCLICKED()"); + pCaller->m_hwndWPForm = (HWND) wpfForm->W32BUTTONCLICKED(); + break; + + case (WM_USER + WM_ACTIVATE): + if((LOWORD(msg.wParam) == WA_ACTIVE) || + (LOWORD(msg.wParam) == WA_CLICKACTIVE)) + { + if(HIWORD(msg.wParam) == 0) + wpfForm->WindowEvent_WindowActivated(); + } + else if(LOWORD(msg.wParam) == WA_INACTIVE) + { + if(HIWORD(msg.wParam) == 0) + wpfForm->WindowEvent_WindowDeactivated(); + } + break; + + case (WM_USER + WM_SIZE): + if(msg.wParam == SIZE_MAXIMIZED) + wpfForm->WindowEvent_MaximizeOccured((long)HIWORD(msg.lParam),(long)LOWORD(msg.lParam)); + + else if(msg.wParam == SIZE_MINIMIZED) + wpfForm->WindowEvent_MinimizeOccured(); + + break; + + //// + // Client Window Events * WPFThreadProc sends them to a Event Dispatcher + // via COM to let C# know about these * + //// + case (WM_CLIENT_EVENT_MDICHILDWINDOWSWITCHOCCURED): + case (WM_CLIENT_EVENT_PARENTGETSETTEXTOCCURED): + case (WM_CLIENT_EVENT_PARENTSETFOCUSOCCURED): + { + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT ReResolve() forwarding it to WPFButton"); + EventDispatcherForwarder->ReResolve(GetCurrentProcessId(),(long)hWnd); // Ideally only switches of active document occur this way + } + break; + + case (WM_CLIENT_EVENT_PARENTNOTIFYLBUTTONCLICKOCCURED): + case (WM_CLIENT_EVENT_PARENTNOTIFYWMCREATEOCCURED): + case (WM_CLIENT_EVENT_PARENTCLOSEWITHOUTDESTROYOCCURED): + { + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT PossArtifactAddedDeleted() forwarding it to WPFButton"); + //EventDispatcherForwarder->ReResolve(GetCurrentProcessId(),(long)hWnd); + } + break; + + case (WM_CLIENT_EVENT_DRAGNDROPOCCURED): + { + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT DragNDropOccured() forwarding it to WPFButton"); + EventDispatcherForwarder->DragNDropOccured(GetCurrentProcessId(),(long)hWnd,pCaller->m_nDragDroppedFilesCount,pCaller->m_bstrDragDroppedFilesSemiColonSep); + } + break; + + case (WM_CLIENT_EVENT_OPENFILEORSAVEASDIALOGOCCURED): + { + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT OpenOrSaveFileDialogOccured() forwarding it to WPFButton"); + _bstr_t possLocAndFileName(pCaller->m_strFileNameLocationBuf); + _bstr_t FileTypes(pCaller->m_strFileTypesBuf); + EventDispatcherForwarder->OpenOrSaveFileDialogOccured(GetCurrentProcessId(), (long)hWnd, possLocAndFileName, FileTypes); + } + break; + } + } + } + + // Let the WPF Form know that this thread is exiting to allow it to do + // any cleanup it may want to do + STOPPING_THREAD: + + log(LOGGING_LOW, L"EventDispatcherHandler - hWindow %u Deactivation Occured for PID %u", hWnd,::GetCurrentProcessId()); + wpfForm->WPFThreadProc_ButtonWPForm_Deactivated(); + + // Also let the Client Event know the same thing + log(LOGGING_DEBUG, L"WM_CLIENT_EVENT hWndLastDeactivate() forwarding it to WPFButton for PID %u and hWnd %u", ::GetCurrentProcessId(), hWnd); + EventDispatcherForwarder->hWndLastDeactivate(GetCurrentProcessId(), (long)hWnd); + + } + catch(...) + { + log(LOGGING_LOW, L"*Error* - A fatal Error Occured in WPFThreadProc WpfButton. Exiting..."); + } + } + else + { + log(LOGGING_LOW, L"Error occured creating WPForm Instance COM %i. Exiting...",hr); + } + + pCaller->m_bThreadIsReady = false; + CoUninitialize(); + return 0; +} +//******************************************************************** +// Class WPFCaller +// +// Programmer Daniel Romischer +// Ooganizer Development Team +// +// Description ~This class holds the default wndproc to process all the +// messages and send them to the WPF COM Object via the COM Thread. +// +// Note ~ All the host's Windows Messages enter in on OnDefault() +// +// Created 05-26-2008 +//******************************************************************** +////////////////////////////////////////////////////////////////////// +//******************************************************************** +// Construction / Destruction +//******************************************************************** +////////////////////////////////////////////////////////////////////// +WPFCaller::WPFCaller(HookWndItem Item, HINSTANCE hInstance): +m_hWnd(Item.hWnd), +m_hwndWPForm(NULL), +m_hwndW32Window(NULL), +m_DefWndProc(Item.DefWndProc), +m_HookWndProc(Item.HookWndProc), +m_thread(NULL), +m_threadID(0), +m_bThreadIsReady(false), +m_hInst(hInstance), +m_wndHeight(0), +m_wndWidth(0), +m_ButtonState(BUTTON_NONE), +m_ButtonToggledState(BUTTON_NONE), +m_ButtonStateLastSaved(BUTTON_NONE), +m_ButtonToggledStateLastSaved(BUTTON_NONE), +m_bButtonIsArtificiallyHidden_MOVE(false), +m_bButtonIsMinimized(false), +m_bButtonIsBeingRestored(false), +m_StartCloseButNotDestroyTimerCount(0), +m_nDragDroppedFilesCount(0) +{ + + // Allow us access to the static DS *only load once* + if(s_WPFCallerAccess == NULL) + s_WPFCallerAccess = new CWHPaccess(); + + // just to make sure (to avoid any thread issues) assign out the this instance + // BEFORE creating the threads *below*. + Item.wpfcaller = this; + if(s_WPFCallerAccess->SetHookedWndItem(Item.hWnd, Item) == FALSE) + log(LOGGING_LOW, L"WPFCaller SetHookedWndItem FAILED!! (THIS IS NOT GOOD!)"); + + // Create the COM WPF Object for WPF Power and Flexibility + m_thread = CreateThread(NULL,0,&WPFThreadProc,(LPVOID)this,0,&m_threadID); + + if(m_threadID > 0) + log(LOGGING_HIGH, L"WPFCaller Spawned WPFThreadID %i",m_threadID); + else + log(LOGGING_LOW, L"Error - WPFCaller Failed to Spawn WPFThread",m_threadID); + + // Clear FileName/Types Buffer + memset(m_strFileNameLocationBuf,0,(MAX_PATH + 1)); + memset(m_strFileTypesBuf,0,(MAX_PATH + 1)); + + // We are creating a new Thread to deal with 2 windows (WPForm Window, + // Start Window32 Button (for speed) + Start(); +} +WPFCaller::~WPFCaller() +{ + log(LOGGING_DEBUG, L"~WPFCaller() got called"); + + // Destroy the Button Window + if(m_hwndW32Window && ::IsWindow(m_hwndW32Window)) + ::DestroyWindow(m_hwndW32Window); + + // Destroy the COM Thread + if(m_bThreadIsReady) + { + // First let's make sure the thread is even still running and valid, + // an error could have closed down the thread. Let's check if the handle + // gives us a valid id. + DWORD dwThreadId = GetThreadId(m_thread); + bool bThreadIsValid = ((dwThreadId != 0) && (dwThreadId == m_threadID)); + + // if this thread is not valid no need to continue below + if(!bThreadIsValid) + log(LOGGING_LOW, L"WPFThread ID %i was invalid when compared to Id %i, ~thread must already have been closed. An error must have occured", m_threadID, dwThreadId); + + if(bThreadIsValid) + { + // Pass QUIT Message to the COM Thread + log(LOGGING_DEBUG, L"Posting WM_KILLTHREAD Message to COM Thread %i", m_threadID); + PostThreadMessage(m_threadID, WM_KILLTHREAD, NULL, NULL); + + // We need to wait to make sure COM deallocated before exiting, + // otherwise the WPForm remains active, because deallocation never occurs + while(m_bThreadIsReady) + Sleep(20); + + log(LOGGING_DEBUG, L"Closing Thread Handle to Thread %i", m_threadID); + CloseHandle(m_thread); + + // Also Unregister all Window Classes here + //UnregisterClass(L"W32ButtonHookWndClass", m_hInst); + } + else + { + log(LOGGING_LOW, L"Did NOT close WPFThread m_bThreadIsReady was not true - this should mean WPFThread closed due to an error with COM"); + } + } + else + { + log(LOGGING_LOW, L"Did NOT close WPFThread m_bThreadIsReady was not true - this should mean WPFThread closed due to an error with COM"); + } +} +///////////////////////////////////////////////////////////////////// +// Desc: Get the Alpha Channel / Opaqueness of the Button +///////////////////////////////////////////////////////////////////// +BYTE WPFCaller::GetAlpha() +{ + COLORREF pcrKey; + BYTE pbAlpha; + DWORD dwFlags; + GetLayeredWindowAttributes(m_hwndW32Window, &pcrKey, &pbAlpha, &dwFlags); + return pbAlpha; +} +///////////////////////////////////////////////////////////////////// +// Desc: Set the Alpha Channel / Opaqueness for the Button +///////////////////////////////////////////////////////////////////// +void WPFCaller::SetAlpha(BYTE bAlpha) +{ + SetLayeredWindowAttributes(m_hwndW32Window, RGB(255,255,255),bAlpha, LWA_COLORKEY|LWA_ALPHA); +} +///////////////////////////////////////////////////////////////////// +// Desc: Use this to start the Fade event on the Button +///////////////////////////////////////////////////////////////////// +void WPFCaller::StartRestoreEventFadeTimer() +{ + log(LOGGING_DEBUG, L"Launching Restore Event Timer..."); + SetAlpha(0); // Hide Button Completly + SetTimer(m_hwndW32Window, NID_RESTORE_EVENT_TIMER,20,NULL); +} +///////////////////////////////////////////////////////////////////// +// Desc: Use this when a WM_CLOSE message is received. Some Apps won't +// close when this event occurs (but rather close an artifact), +// ~this allows us to detect this occurance +///////////////////////////////////////////////////////////////////// +void WPFCaller::StartCloseButNotDestroyTimer() +{ + // quarter of a second is more than enough time to know whether an app closed or not + // ~but just in case we'll run the timer multiple times over and over + m_StartCloseButNotDestroyTimerCount = 0; + log(LOGGING_DEBUG, L"Launching CloseButNotDestroyTimer..."); + SetTimer(m_hwndW32Window, NID_CLOSE_BUT_NOT_DESTROY_EVENT_TIMER,250,NULL); +} +///////////////////////////////////////////////////////////////////// +// Func: EventDispatcherHandler() +// Desc: Responsible for sending certain client events to the WPFThreadProc +// This allows us to be more interactive. +// +// Note: Not all Client events are handled here *only the easiest ones* +////////////////////////////////////////////////////////////////////// +void WPFCaller::EventDispatcherHandler(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) +{ + + switch(Msg) + { + // DragNDropOccured + case WM_DROPFILES: + { + HDROP hdrop = (HDROP) wParam; + wchar_t buf[MAX_PATH + 1] = {0}; + + m_bstrDragDroppedFilesSemiColonSep = L""; + m_nDragDroppedFilesCount = DragQueryFile(hdrop,0xFFFFFFFF,NULL,0); + //log(LOGGING_DEBUG, L"EventDispatcherHandler - hWindow %u received %d Dropped Files", hWnd, m_nDragDroppedFilesCount); + + for(int i = 0; i < m_nDragDroppedFilesCount; ++i) + { + if(i > 0) + m_bstrDragDroppedFilesSemiColonSep += L";"; + + DragQueryFile(hdrop,i,buf,MAX_PATH); + //log(LOGGING_DEBUG, L"EventDispatcherHandler - File %u - received dropped file %s", i, (char*) buf); + lstrcat((wchar_t *)m_bstrDragDroppedFilesSemiColonSep, buf); + } + + // Let WPFCaller know + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_DRAGNDROPOCCURED ,0,0); + } + break; + + // MDIChildWindowSwitchOccured + case WM_KEYDOWN: + { + // Did Ctrl + F6 or Ctrl + Tab get pushed, if so a possible MDI + // switch occured so relay that information + if((wParam == VK_TAB || wParam == VK_F6) && + (GetKeyState(VK_CONTROL) < 0)) + { + // Let WPFCaller know + //log(LOGGING_DEBUG, L"EventDispatcherHandler - Ctrl + F6 or Ctrl + Tab got pushed - poss. MDIChildWindowSwitch occured"); + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_MDICHILDWINDOWSWITCHOCCURED ,0,0); + } + } + break; + + // ParentGetSetTextOccured + case WM_GETTEXT: + case WM_SETTEXT: + { + // Let WPFCaller know + //log(LOGGING_DEBUG, L"EventDispatcherHandler - ParentGetSetText Occured - poss. MDIChildWindowSwitch occured"); + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_PARENTGETSETTEXTOCCURED,0,0); + } + break; + + // ParentNotifyLButtonClick Occured + // ParentNotifyWMCreate Occured + case WM_PARENTNOTIFY: + { + WORD wMsg = LOWORD(wParam); + switch(wMsg) + { + case WM_CREATE: + { + // Let WPFCaller know + //log(LOGGING_DEBUG, L"EventDispatcherHandler - ParentNotify WM_CREATE Occured - poss. MDIChildWindow Creation occured"); + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_PARENTNOTIFYWMCREATEOCCURED,0,0); + } + break; + + case WM_LBUTTONDOWN: + { + // Let WPFCaller know + //log(LOGGING_DEBUG, L"EventDispatcherHandler - ParentNotify LBUTTONDOWN Occured - poss. MDIChildWindowSwitch occured"); + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_PARENTNOTIFYLBUTTONCLICKOCCURED,0,0); + } + break; + } + } + break; + + // Parent received a WM_CLOSE but didn't destroy itself + case WM_CLOSE: + { + //log(LOGGING_DEBUG, L"EventDispatcherHandler - Received WM_CLOSE running StartCloseButNotDestroyTimer()"); + StartCloseButNotDestroyTimer(); // Win32Button will let the WPFCaller know + } + break; + + // Parent received focus message + case WM_SETFOCUS: + { + // Let WPFCaller know + //log(LOGGING_DEBUG, L"EventDispatcherHandler - Parent SetFocus Occured - poss. MDIChildWindowSwitch occured"); + PostThreadMessage(m_threadID, WM_CLIENT_EVENT_PARENTSETFOCUSOCCURED,0,0); + } + break; + } +} +///////////////////////////////////////////////////////////////////// +// Func: HandleDDEMessages() +// Desc: Because DDE is a message-based protocol, it employs no functions or libraries. +// All DDE transactions are conducted by passing certain defined DDE messages between the +// client and server windows. +// ~We may need to use this for certain applications to listen in +// +// Note: We call this OnDefault(), because DDE message can get passed into us before WPFThread is up and running +////////////////////////////////////////////////////////////////////// +void WPFCaller::HandleDDEMessages(HWND hWnd, UINT Msg,WPARAM wParam,LPARAM lParam) +{ + switch(Msg) + { + case WM_DDE_ACK: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_ACK"); + break; + + case WM_DDE_ADVISE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_ADVISE"); + break; + + case WM_DDE_DATA: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_DATA"); + break; + + case WM_DDE_EXECUTE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_EXECUTE"); + break; + + case WM_DDE_INITIATE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_INITIATE"); + { + wchar_t strBuf[MAX_PATH] = {0}; + ATOM lowword = LOWORD(lParam); + ATOM highword = HIWORD(lParam); + if(lowword != NULL) + { + int nSize = ::GlobalGetAtomName((ATOM)lowword,strBuf,MAX_PATH); + strBuf[nSize] = 0; + //log(LOGGING_DEBUG, L"Found lowword Atom, %d, with lowword String, %s", lowword, strBuf); + } + if(highword != NULL) + { + int nSize = ::GlobalGetAtomName((ATOM)highword,strBuf,MAX_PATH); + strBuf[nSize] = 0; + //log(LOGGING_DEBUG, L"Found highword Atom, %d, with highword String, %s", highword, strBuf); + } + } + break; + + case WM_DDE_POKE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_POKE"); + break; + + case WM_DDE_REQUEST: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_REQUEST"); + break; + + case WM_DDE_TERMINATE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_TERMINATE"); + break; + + case WM_DDE_UNADVISE: + //log(LOGGING_DEBUG, L"Received DDE Message WM_DDE_UNADVISE"); + break; + } +} +///////////////////////////////////////////////////////////////////// +// Func: OnDefault() +// Desc: Default handler for any WM_message received (ALL except WM_NCDESTROY +// and m_msgWMUnHook) the Destroy Messages delete this class and are handled +// therefore outside of it +////////////////////////////////////////////////////////////////////// +LRESULT WPFCaller::OnDefault(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) +{ + LRESULT result = 0; + try + { + + // Handle DDE Messages + HandleDDEMessages(hWnd,Msg,wParam,lParam); + + // If this is a custom message forward it our Button, + // it will be the main handler for our custom messages because it can communicate + // to the COMThread as well as manipulate the Button (we can skip and return the value) + if((m_hwndW32Window != NULL) && (g_IsMessageACustomMessage(Msg))) + { + return SendMessage(m_hwndW32Window,Msg,wParam,lParam); + } + + // regular messages that our W32Button Cares about it, send it (no WM_USER offset needed here) + if((m_hwndW32Window != NULL) && (g_IsMessageW32WindowCaresAbout(Msg))) + { + // work-around for Minimize/Restore. Let the parent communicate + // to the child that it is being redrawn + if(Msg == WM_PAINT && m_bButtonIsMinimized) + { + wParam = (WPARAM) m_hWnd; + lParam = (LPARAM) m_hWnd; + PostMessage(m_hwndW32Window, Msg, wParam, lParam); + } + else + { + SendMessage(m_hwndW32Window, Msg, wParam, lParam); + } + } + + // We pass the Messages we care about forward to our COM/W32/WPF Thread + if(m_bThreadIsReady && (m_threadID != 0)) + { + // IF our COM object cares about this, send it + if(g_IsMessageWPFormCaresAbout(Msg)) + { + // We error if we use PostThreadMessage with message < WM_USER so we offset it + PostThreadMessage(m_threadID,(WM_USER + Msg),wParam,lParam); + } + + // our Event Dispatcher maybe interested in this + // message let it know about it + EventDispatcherHandler(hWnd,Msg,wParam,lParam); + } + + // Call the Default Window Proc - IMPORTANT - Always do this + result = CallWindowProc(m_DefWndProc, hWnd, Msg, wParam, lParam); + } + catch(...) + { + log(LOGGING_LOW, L"*Error* - A Fatal Error occured in WpfCaller's OnDefault() - (This can't be good)"); + } + return result; +} +////////////////////////////////////////////////////////////////////// +// Func: threadproc +// Desc: Thread Entry Point responsible for Dispatching the W32Window Messages +// +// Note: We are on purpose Ignoring Error Msg 1410. If the window class is already registered it +// will throw an error, we can safely continuen and instantiate the window class +////////////////////////////////////////////////////////////////////// +int WINAPI WPFCaller::threadproc(HINSTANCE hinstance, HINSTANCE hPrevInstance, void* vArg, int nCmdShow) +{ + if (!InitApplication(hinstance)) + { + // "Class already exists" this happens if the + // same window get's called again to be hooked into. + // this error can safely be ignored. + if(!(GetLastError() == 1410)) + { + log(LOGGING_LOW, L"initApplication failed error %i",GetLastError()); + return FALSE; + } + } + + if (!InitInstance(hinstance, nCmdShow)) + { + log(LOGGING_LOW, L"initInstance failed error %i",GetLastError()); + return FALSE; + } + + MSG msg; + BOOL bGotMessage; + m_bThreadIsReady = true; // Thread is up N' Ready and Receiving Messages + while ((bGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 ) + { + if(bGotMessage == -1) + { + // handle the error and possible exit + log(LOGGING_LOW, L"An Error Occured in ThreadProc Messaging. Exiting!"); + ExitThread(0); + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return msg.wParam; +} +////////////////////////////////////////////////////////////////////// +// Func: InitApplication() +// Desc: Responsible for setting up the WNDCLASSEX struct and register +// the transparent window with Windows via RegisterClassEx() +// +// Retr: TRUE, if successful, FALSE otherwise +////////////////////////////////////////////////////////////////////// +BOOL WPFCaller::InitApplication(HINSTANCE hInstance) +{ + // Fill in the window class structure with parameters + // that describe the main window. + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(wcx); // size of structure + wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes + wcx.lpfnWndProc = (WNDPROC) W32WndProc; // points to W32 window procedure + wcx.cbClsExtra = 0; // no extra class memory + wcx.cbWndExtra = 0; // no extra window memory + wcx.hInstance = hInstance; // handle to instance + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); // predefined arrow + wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); // white background brush + wcx.lpszMenuName = L"MainMenu"; // name of menu resource + wcx.lpszClassName = L"W32ButtonHookWndClass"; // name of window class + wcx.hIconSm = NULL; + + // Register the window class. *may throw error 1410* + return RegisterClassEx(&wcx); +} +////////////////////////////////////////////////////////////////////// +// Func: InitInstance() +// Desc: Responsible for Creating and Showing a new Window Class Instance +// +// Retr: TRUE, if successful, FALSE otherwise +////////////////////////////////////////////////////////////////////// +BOOL WPFCaller::InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + // Get the Dimensions of the hooked in Window + RECT rect; + GetWindowRect(m_hWnd,&rect); + + // set owner/parent window + HWND hParent = m_hWnd; + DWORD dwStyle; + + //dwStyle = ( WS_POPUP | WS_BORDER ); // For Debugging + dwStyle = ( WS_POPUP ); + + // If parent Window get's hidden for some reason, should we hide this window? + // by default owned windows don't hide, when their parent is hidden, + // they do hide when parent is minimized. + log(LOGGING_DEBUG, L"Calling CreateWindowEx with Parent %i", hParent); + + //( WS_POPUP | WS_BORDER ), // top-level window + m_hwndW32Window = CreateWindowEx( + ( WS_EX_LAYERED ), // A Layered window is by default transparent + L"W32ButtonHookWndClass", // name of window class + L"W32ButtonHookWndTitle",// title-bar string + dwStyle, // top-level window + rect.left, // default horizontal position + rect.top, // default vertical position + (rect.right - rect.left), // default width + (rect.bottom - rect.top), // default height + (HWND) hParent, // set owner window + // ~An owned window is always above its owner in the Z order and + // is hidden when its owner is minimized + (HMENU) NULL, // use class menu + hInstance, // handle to application instance + (LPVOID) NULL); // no window-creation data + + log(LOGGING_DEBUG, L"CreateWindowEx returns (m_hwndW32Window is set to %i) ", m_hwndW32Window); + + // we can use this to fade the window if we want too... (something to think about...) + //if(SetLayeredWindowAttributes(m_hwndW32Window, RGB(255,255,255),255, LWA_COLORKEY|LWA_ALPHA)){} + SetLayeredWindowAttributes(m_hwndW32Window, RGB(255,255,255),255, LWA_COLORKEY|LWA_ALPHA); + + // Show the window and send a WM_PAINT message to the window procedure. + ShowWindow(m_hwndW32Window, nCmdShow); + UpdateWindow(m_hwndW32Window); + + return (m_hwndW32Window != NULL); +} \ No newline at end of file diff --git a/Hooks/ButtonHook/WPFCaller.h b/Hooks/ButtonHook/WPFCaller.h new file mode 100644 index 0000000..e1cb7fb --- /dev/null +++ b/Hooks/ButtonHook/WPFCaller.h @@ -0,0 +1,171 @@ +#pragma once + +#include "thread.h" + +#ifdef _DEBUG + #import "..\\..\\Target\\Debug\\ButtonWPForm.tlb" +#else + #import "..\\..\\Target\\Release\\ButtonWPForm.tlb" +#endif +using namespace ButtonWPForm; + +namespace Ooganizer +{ + + enum BUTTON_STATE + { + // These are the states that coincide with the states defined + // in ButtonWPFormCCW + BUTTON_NONE = 1, + BUTTON_DOWN = 2, // BUTTON_ADD + BUTTON_TOGGLED = 3, // BUTTON_DELETE + + // Button Up is the Hover image (Used on Mouse Over), + // it is NOT DEFINED in BHInteracter + BUTTON_UP = 1000 + }; + + //// + // ButtonThemeSetting, this static holds our current Button Theme Setting + // ~This structure can be reloaded when a ThemeChange occured (WM_THEMECHANGED) + //// + struct ButtonThemeSetting + { + // Init Flags + bool bIsInitialized; + bool bIsChanged; + + // Int Button Dimension/Location + long Top; + long Right; + long Height; + long Width; + + // String Button Locations + _bstr_t bstrBUTTON_UP; + _bstr_t bstrBUTTON_DOWN; + _bstr_t bstrTOGGLE_UP; + + ButtonThemeSetting() + { + Top = 0; + Right = 0; + Height = 0; + Width = 0; + bIsInitialized = false; + bIsChanged = false; + } + }; + + class CWHPaccess; + class WPFCaller; + + #define BLANK_HookWndItem(n) HookWndItem n = {NULL,NULL,NULL,NULL} + ////////////////////////////////////////////////////////////////////// + // Strc: HookWndItem + // Desc: Hook Item is used in the HookedWndList. Each HookWndItem keeps track + // of all the addresses needed for each hook for each Windows, + // as well as each Window's WPFCaller. + ////////////////////////////////////////////////////////////////////// + struct HookWndItem + { + HWND hWnd; + WNDPROC HookWndProc; + WNDPROC DefWndProc; + WPFCaller* wpfcaller; + }; + ////////////////////////////////////////////////////////////////////// + // Clss: WPFCaller + // Desc: This class is responsible for overriding wndproc draw routines + // and communicate to the WPF COM object + ////////////////////////////////////////////////////////////////////// + class WPFCaller : Thread + { + public: + // All Windows Messages *Except NCDestroy & UnHook* enter here + virtual LRESULT OnDefault (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam); + WPFCaller(HookWndItem Item, HINSTANCE hInstance); + ~WPFCaller(); + + // Each WPFCaller is mapped to a HookWndItem (Hooked Window) + HWND m_hWnd; + WNDPROC m_HookWndProc; + WNDPROC m_DefWndProc; + HINSTANCE m_hInst; + + // Window W32 State Settings + // ~we are keeping track of the Hooked W32 sizes + int m_wndHeight; + int m_wndWidth; + RECT m_wndRECT; + + // We need to keep track of the Button State in order + // to know what to draw + BUTTON_STATE m_ButtonState; + BUTTON_STATE m_ButtonToggledState; // We can overwrite buttonDown state + // with another state. this allows us to + // specify which state to use to overwrite. + + BUTTON_STATE m_ButtonStateLastSaved; + BUTTON_STATE m_ButtonToggledStateLastSaved; + bool m_bButtonIsArtificiallyHidden_MOVE; + bool m_bButtonIsMinimized; + bool m_bButtonIsBeingRestored; + + // Transparency / Fade Effect + BYTE GetAlpha(); + void SetAlpha(BYTE bAlpha); + void StartRestoreEventFadeTimer(); + + // Client Events + void StartCloseButNotDestroyTimer(); + int m_StartCloseButNotDestroyTimerCount; + + // Drag N' Dropped Files + int m_nDragDroppedFilesCount; + _bstr_t m_bstrDragDroppedFilesSemiColonSep; + + // OpenFile or FileSaveAs Dialog Prms Passing + wchar_t m_strFileNameLocationBuf[MAX_PATH + 1]; + wchar_t m_strFileTypesBuf[MAX_PATH + 1]; + + // WPFProc Will load the Button Settings via COM which + // we'll use to draw the Icon + ButtonThemeSetting m_ButtonThemeSetting; + + // Window Handles + HWND m_hwndWPForm; // passed back to us by ButtonWPForm + HWND m_hwndW32Window; // our w32 Button + + // ThreadStuff (WPFComThread) + bool m_bThreadIsReady; + HANDLE m_thread; + DWORD m_threadID; + + private: + + // OnDefault() uses this function to possible send messages + // to the EventDispatcher in C# for further processing + void EventDispatcherHandler(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam); + + // We don't need to right now, but we may need it more in the future. + // Office passes in startup file prms via DDE (other apps may too) + void HandleDDEMessages(HWND hWnd, UINT Msg,WPARAM wParam,LPARAM lParam); + + // Win32 Button Window * Created for better speed * + // Responsible for setting up the WNDCLASSEX struct and register the Window + BOOL InitApplication(HINSTANCE hInstance); + + // Responsible for Creating and Showing a new Window Class Instance + BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); + + // Thread Entry + int WINAPI threadproc(HINSTANCE hinstance, HINSTANCE hPrevInstance, void* vArg, int nCmdShow); + + // Thread Entry + virtual DWORD Run(LPVOID vArg) + { + return(threadproc(m_hInst,NULL,vArg,TRUE)); + } + }; +} \ No newline at end of file diff --git a/Hooks/ButtonHook/resource.h b/Hooks/ButtonHook/resource.h new file mode 100644 index 0000000..3135bc0 --- /dev/null +++ b/Hooks/ButtonHook/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ButtonHook.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Hooks/ButtonHook/thread.h b/Hooks/ButtonHook/thread.h new file mode 100644 index 0000000..2b1d418 --- /dev/null +++ b/Hooks/ButtonHook/thread.h @@ -0,0 +1,100 @@ +#pragma once + +namespace Ooganizer +{ + // Generic Thread Class! + class Thread + { + public: + + // Starts the thread + // This function starts the thread pointed by m_pThreadFunc with default attributes + DWORD Start( void* arg = NULL ) + { + m_ThreadCtx.m_pUserData = arg; + m_ThreadCtx.m_hThread = CreateThread(NULL, 0, m_pThreadFunc, this, 0, &m_ThreadCtx.m_dwTID); + m_ThreadCtx.m_dwExitCode = (DWORD)-1; + return GetLastError(); + } + + // Stops the thread. + // This function stops the current thread + DWORD Stop ( bool bForceKill = false ) + { + log(LOGGING_HIGH, L"Hidden Wnd Thread Stopped()"); + if ( m_ThreadCtx.m_hThread ) + { + GetExitCodeThread(m_ThreadCtx.m_hThread, &m_ThreadCtx.m_dwExitCode); + + if ( m_ThreadCtx.m_dwExitCode == STILL_ACTIVE && bForceKill ) + TerminateThread(m_ThreadCtx.m_hThread, DWORD(-1)); + + m_ThreadCtx.m_hThread = NULL; + } + return m_ThreadCtx.m_dwExitCode; + } + + // Returns Thread Exit Code + DWORD GetExitCode() const + { + if ( m_ThreadCtx.m_hThread ) + GetExitCodeThread(m_ThreadCtx.m_hThread, (LPDWORD)&m_ThreadCtx.m_dwExitCode); + return m_ThreadCtx.m_dwExitCode; + } + + // Attaches a Thread Function + // Used primarily for porting but can serve in developing generic thread objects + void Attach( LPTHREAD_START_ROUTINE lpThreadFunc ){ + m_pThreadFunc = lpThreadFunc; + } + + // Detaches the Attached Thread Function + // Detaches the Attached Thread Function, If any. + void Detach( void ){ + m_pThreadFunc = Thread::EntryPoint; + } + + Thread(){ m_pThreadFunc = Thread::EntryPoint; /*Can call Detach Also*/ } + //plug-in constructor + Thread(PTHREAD_START_ROUTINE lpExternalRoutine){Attach(lpExternalRoutine);} + ~Thread(){ if(m_ThreadCtx.m_hThread) Stop(true);} + + protected: + + // Std Template: Override if you are sure of what you are doing + static DWORD WINAPI EntryPoint( LPVOID pArg) + { + Thread *pParent = reinterpret_cast(pArg); + pParent->ThreadCtor(); + pParent->Run( pParent->m_ThreadCtx.m_pUserData ); + pParent->ThreadDtor(); + return STILL_ACTIVE; + } + + // Override this method with the body/code of your thread + virtual DWORD Run( LPVOID /*arg */){return m_ThreadCtx.m_dwExitCode;} + // override this function to provide your extra initialization + virtual void ThreadCtor(){} + // Override this function to provide your extra destruction + virtual void ThreadDtor(){} + + //// + // Thread Context Inner Class (UserData Pointer, Handle, Thread ID) + //// + class CThreadContext + { + public: + CThreadContext(){memset(this, 0, sizeof(this));} + + // Attributes + public: + HANDLE m_hThread; // The Thread Handle + DWORD m_dwTID; // The Thread ID + LPVOID m_pUserData; // The user data pointer + LPVOID m_pParent; // The this pointer of the parent CThread object + DWORD m_dwExitCode; // The Exit Code of the thread + + } m_ThreadCtx; // The Thread Context Member + LPTHREAD_START_ROUTINE m_pThreadFunc; // The Worker Thread Function Pointer + }; +} \ No newline at end of file diff --git a/Hooks/CaptionButton/CaptionButton.Designer.cs b/Hooks/CaptionButton/CaptionButton.Designer.cs new file mode 100644 index 0000000..55ba685 --- /dev/null +++ b/Hooks/CaptionButton/CaptionButton.Designer.cs @@ -0,0 +1,57 @@ +namespace Foo.Hooks.CaptionButton +{ + partial class CaptionButton + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // CaptionButton + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.ControlText; + this.ClientSize = new System.Drawing.Size(10, 10); + this.ControlBox = false; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CaptionButton"; + this.Opacity = 0.0; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.WindowState = System.Windows.Forms.FormWindowState.Minimized; + this.Load += new System.EventHandler(this.CaptionButton_Load); + this.HandleCreated += new System.EventHandler(CaptionButton_HandleCreated); + this.Shown += new System.EventHandler(CaptionButton_Shown); + this.ResumeLayout(false); + } + + #endregion + } +} + diff --git a/Hooks/CaptionButton/CaptionButton.cs b/Hooks/CaptionButton/CaptionButton.cs new file mode 100644 index 0000000..b10a3e4 --- /dev/null +++ b/Hooks/CaptionButton/CaptionButton.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Reflection; + +using Foo.Platform; +using Foo.Platform.Interacters; + +namespace Foo.Hooks.CaptionButton +{ + public partial class CaptionButton : Form + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + [DllImport("user32.dll")] + public static extern Int32 GetWindowLong(IntPtr hwnd, int nIndex); + + [DllImport("user32.dll")] + public static extern Int32 SetWindowLong(IntPtr hwnd, int nIndex, Int32 dwNewLong); + + [DllImport("user32.dll")] + public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, Int32 crKey, int bAlpha, uint dwFlags); + + public const int GWL_EXSTYLE = -20; + public const int LWA_COLORKEY = 0x00000001; + public const int WS_EX_LAYERED = 0x00080000; + + [StructLayout(LayoutKind.Sequential)] + struct COLORREF + { + public byte R; + public byte G; + public byte B; + } + + public CaptionButton() + { + InitializeComponent(); + } + + ~CaptionButton() + { + } + + protected override void WndProc(ref Message m) + { + // Debug Only *Allows us to step right into buttonhook starting * + if (Program.DEBUG_ONLY_SETTING_STARTBUTTONHOOK && + !Program.DEBUG_ONLY_SETTING_STARTBUTTONHOOK_IS_STARTED) + { + Log.Info(string.Format("{0}() - * Debug Only Option * Starting ButtonHook", MethodBase.GetCurrentMethod().Name)); + BHInteracter.StartButtonHookDLLEntryW(); + Program.DEBUG_ONLY_SETTING_STARTBUTTONHOOK_IS_STARTED = true; + } + + if (m.Msg == BHInteracter.WM_CAPTIONBUTTON_START) + { + Log.Info(string.Format("{0}() - Received CAPTIONBUTTON_START Message", MethodBase.GetCurrentMethod().Name)); + BHInteracter.StartButtonHookDLLEntryW(); + } + else if (m.Msg == BHInteracter.WM_CAPTIONBUTTON_STOP) + { + Log.Info(string.Format("{0}() - Received CAPTIONBUTTON_STOP Message", MethodBase.GetCurrentMethod().Name)); + BHInteracter.StopButtonHookDLLEntryW(); + } + + // force opacity at all times + if (Opacity == 1.0) + Opacity = 0.0; + + // force minimized at all times + if (WindowState != FormWindowState.Minimized) + WindowState = FormWindowState.Minimized; + + // force Not to be seen in taskbar + if (ShowInTaskbar == true) + ShowInTaskbar = false; + + base.WndProc(ref m); + } + + void CaptionButton_Shown(object sender, System.EventArgs e) + { + Hide(); + } + + private void CaptionButton_HandleCreated(object sender, EventArgs e) + { + IntPtr hWnd = this.Handle; + SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); + SetLayeredWindowAttributes(hWnd, 0x00000000, 0, LWA_COLORKEY); + } + + void CaptionButton_Load(object sender, System.EventArgs e) + { + Log.Info(string.Format("{0}() - CaptionButton Load Called! - passing out hWnd Handle {1}", MethodBase.GetCurrentMethod().Name,Handle.ToInt32())); + TemporaryVal.SetValI(Handle.ToInt32()); + } + } +} diff --git a/Hooks/CaptionButton/CaptionButton.csproj b/Hooks/CaptionButton/CaptionButton.csproj new file mode 100644 index 0000000..b37f858 --- /dev/null +++ b/Hooks/CaptionButton/CaptionButton.csproj @@ -0,0 +1,115 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {3854981D-5F6B-4AC5-A3F9-5C3761838821} + WinExe + Properties + Foo.Hooks.CaptionButton + CaptionButton + v3.5 + 512 + + + + + + + + + true + MyKeyFile.SNK + + + true + full + false + ..\..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\Target\Release\ + TRACE + prompt + 4 + + + + False + ..\..\Components\log4net.dll + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + Form + + + CaptionButton.cs + + + + + CaptionButton.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + + + + + + + \ No newline at end of file diff --git a/Hooks/CaptionButton/CaptionButton.resx b/Hooks/CaptionButton/CaptionButton.resx new file mode 100644 index 0000000..ff31a6d --- /dev/null +++ b/Hooks/CaptionButton/CaptionButton.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Hooks/CaptionButton/MyKeyFile.SNK b/Hooks/CaptionButton/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Hooks/CaptionButton/MyKeyFile.SNK differ diff --git a/Hooks/CaptionButton/Program.cs b/Hooks/CaptionButton/Program.cs new file mode 100644 index 0000000..337ec3f --- /dev/null +++ b/Hooks/CaptionButton/Program.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +// Ooganizer Namespaces +using Foo.Platform; +using Foo.Platform.Interacters; + +namespace Foo.Hooks.CaptionButton +{ + static class Program + { + static string DEBUG_ONLY_SETTING_STARTBUTTONHOOK_CMD_STRING = "/StartButtonHook"; + static internal bool DEBUG_ONLY_SETTING_STARTBUTTONHOOK = false; + static internal bool DEBUG_ONLY_SETTING_STARTBUTTONHOOK_IS_STARTED = false; + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + //// + // We want to make sure that we are getting the correct command line params + // otherwise we won't allow this .exe to start + //// + bool bStartButtonHook = false; + string[] args = Environment.GetCommandLineArgs(); + foreach (string arg in args) + { + if(!bStartButtonHook) + bStartButtonHook = (arg == BHInteracter.CAPTIONBUTTON_CMDLINE); + + if(!DEBUG_ONLY_SETTING_STARTBUTTONHOOK) + DEBUG_ONLY_SETTING_STARTBUTTONHOOK = (arg == DEBUG_ONLY_SETTING_STARTBUTTONHOOK_CMD_STRING); + } + + // Should only start if this exe is called through Platform's BHInteracter + if (bStartButtonHook) + { + Application.Run(new CaptionButton()); + } + } + } +} diff --git a/Hooks/CaptionButton/Properties/AssemblyInfo.cs b/Hooks/CaptionButton/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e215914 --- /dev/null +++ b/Hooks/CaptionButton/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OogyCaptionButton")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OogyCaptionButton")] +[assembly: AssemblyCopyright("Copyright © 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3696fc3e-e32a-4a2a-bff3-bd99ce83090f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Hooks/CaptionButton/Properties/Resources.Designer.cs b/Hooks/CaptionButton/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7295cd6 --- /dev/null +++ b/Hooks/CaptionButton/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Hooks.CaptionButton.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.Hooks.CaptionButton.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Hooks/CaptionButton/Properties/Resources.resx b/Hooks/CaptionButton/Properties/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/Hooks/CaptionButton/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Hooks/CaptionButton/Properties/Settings.Designer.cs b/Hooks/CaptionButton/Properties/Settings.Designer.cs new file mode 100644 index 0000000..bb86ec2 --- /dev/null +++ b/Hooks/CaptionButton/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Hooks.CaptionButton.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Hooks/CaptionButton/Properties/Settings.settings b/Hooks/CaptionButton/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/Hooks/CaptionButton/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Oggynize_1.0.sln b/Oggynize_1.0.sln new file mode 100644 index 0000000..15d47c7 --- /dev/null +++ b/Oggynize_1.0.sln @@ -0,0 +1,249 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Platform", "Platform\Platform.csproj", "{F6929AFC-BF61-43A0-BABD-F807B65FFFA1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{3E00D968-DF7D-4836-9A46-980BA5304FEB}" + ProjectSection(SolutionItems) = preProject + Components\log4net.dll = Components\log4net.dll + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Settings", "Settings\Settings.csproj", "{48D75C4F-2749-48BB-9386-721E0E94C144}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hooks", "Hooks", "{D54033AB-5562-487C-A096-AC8D9B185F40}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ButtonHook", "Hooks\ButtonHook\ButtonHook.vcproj", "{5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client Services", "Client Services", "{AE52FFA4-5B75-44C4-B80D-7E406C69868E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ButtonWPForm", "Client Services\ButtonWPForm\ButtonWPForm.csproj", "{E179DF39-539A-407F-94DE-C21F690E02C4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAccessLayer", "DataAccessLayer\DataAccessLayer.csproj", "{C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUILib", "GUILib\GUILib.csproj", "{C1282050-455B-44F4-8520-1C005E38EFB2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Deskband", "Deskband", "{A51A5BDB-B9B7-4B5C-B5D2-57F5B6ABC634}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaptionButton", "Hooks\CaptionButton\CaptionButton.csproj", "{3854981D-5F6B-4AC5-A3F9-5C3761838821}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeskBand", "Deskband\DeskBand\DeskBand.csproj", "{ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BandObject", "Deskband\BandObjectBase\BandObject.csproj", "{BDB3B670-A17B-483E-954C-52FC2B6FF9D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspaceMgr", "WorkspaceMgr\WorkspaceMgr.csproj", "{09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUIWPForms", "Client Services\GUIWPForms\GUIWPForms.csproj", "{A02E052C-3C52-43DB-BB30-A47446B8165F}" + ProjectSection(ProjectDependencies) = postProject + {E179DF39-539A-407F-94DE-C21F690E02C4} = {E179DF39-539A-407F-94DE-C21F690E02C4} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUIDebugStepExe", "Client Services\GUIDebugStepExe\GUIDebugStepExe.csproj", "{4C81A790-31CA-4A71-99AD-339D3837A5C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "zEasyTest", "zEasyTest\zEasyTest.csproj", "{6CDF553C-5060-4871-9CE8-63F66346716A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Satellite", "Satellite\Satellite.csproj", "{6DC93F91-D6D4-4C35-8A83-C180E8E22E16}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{C737AEEA-27C5-494F-8121-3E5C82315DD5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Target", "Target", "{E7CF7E1E-CEAB-4015-BD70-7B2C727BD63E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release", "Release", "{1295F70C-6CDC-4B99-AB85-5305CA8D7103}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debug", "Debug", "{47DF5C34-9275-4F92-8E87-B81B899EBA1F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{208D8FE2-6A2C-438D-9CE9-CB4AAB6B33FD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{113E65CD-E297-4114-9C1B-0446A12D2EE1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddIn.Common", "AddIns\AddIn.Common\AddIn.Common.csproj", "{D32C4454-9334-47AA-9A3F-456B8B12220A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Addin.Office", "AddIns\Addin.Office\Addin.Office.csproj", "{0CA1DD2E-2752-4587-ADB4-77194411648B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Debug|Win32.ActiveCfg = Debug|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Release|Any CPU.Build.0 = Release|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1}.Release|Win32.ActiveCfg = Release|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Debug|Win32.ActiveCfg = Debug|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Release|Any CPU.Build.0 = Release|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {48D75C4F-2749-48BB-9386-721E0E94C144}.Release|Win32.ActiveCfg = Release|Any CPU + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Debug|Win32.Build.0 = Debug|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Release|Any CPU.ActiveCfg = Release|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Release|Mixed Platforms.Build.0 = Release|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Release|Win32.ActiveCfg = Release|Win32 + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B}.Release|Win32.Build.0 = Release|Win32 + {E179DF39-539A-407F-94DE-C21F690E02C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Debug|Win32.ActiveCfg = Debug|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Release|Any CPU.Build.0 = Release|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E179DF39-539A-407F-94DE-C21F690E02C4}.Release|Win32.ActiveCfg = Release|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Release|Any CPU.Build.0 = Release|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618}.Release|Win32.ActiveCfg = Release|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Release|Any CPU.Build.0 = Release|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C1282050-455B-44F4-8520-1C005E38EFB2}.Release|Win32.ActiveCfg = Release|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Debug|Win32.ActiveCfg = Debug|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Release|Any CPU.Build.0 = Release|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3854981D-5F6B-4AC5-A3F9-5C3761838821}.Release|Win32.ActiveCfg = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Debug|Win32.ActiveCfg = Debug|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Any CPU.Build.0 = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7}.Release|Win32.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Debug|Win32.ActiveCfg = Debug|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Any CPU.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3}.Release|Win32.ActiveCfg = Release|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Debug|Win32.ActiveCfg = Debug|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Release|Any CPU.Build.0 = Release|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35}.Release|Win32.ActiveCfg = Release|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Release|Any CPU.Build.0 = Release|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A02E052C-3C52-43DB-BB30-A47446B8165F}.Release|Win32.ActiveCfg = Release|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Release|Any CPU.Build.0 = Release|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4C81A790-31CA-4A71-99AD-339D3837A5C6}.Release|Win32.ActiveCfg = Release|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Release|Any CPU.Build.0 = Release|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6CDF553C-5060-4871-9CE8-63F66346716A}.Release|Win32.ActiveCfg = Release|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Release|Any CPU.Build.0 = Release|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16}.Release|Win32.ActiveCfg = Release|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Release|Any CPU.Build.0 = Release|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {D32C4454-9334-47AA-9A3F-456B8B12220A}.Release|Win32.ActiveCfg = Release|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Debug|Win32.ActiveCfg = Debug|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Release|Any CPU.Build.0 = Release|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0CA1DD2E-2752-4587-ADB4-77194411648B}.Release|Win32.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5E8EB95C-9C4F-4DE3-A5E4-827268AF4E9B} = {D54033AB-5562-487C-A096-AC8D9B185F40} + {3854981D-5F6B-4AC5-A3F9-5C3761838821} = {D54033AB-5562-487C-A096-AC8D9B185F40} + {E179DF39-539A-407F-94DE-C21F690E02C4} = {AE52FFA4-5B75-44C4-B80D-7E406C69868E} + {A02E052C-3C52-43DB-BB30-A47446B8165F} = {AE52FFA4-5B75-44C4-B80D-7E406C69868E} + {4C81A790-31CA-4A71-99AD-339D3837A5C6} = {AE52FFA4-5B75-44C4-B80D-7E406C69868E} + {ACCDA683-C6AC-43DD-819F-4C3DE36E6BD7} = {A51A5BDB-B9B7-4B5C-B5D2-57F5B6ABC634} + {BDB3B670-A17B-483E-954C-52FC2B6FF9D3} = {A51A5BDB-B9B7-4B5C-B5D2-57F5B6ABC634} + {D32C4454-9334-47AA-9A3F-456B8B12220A} = {C737AEEA-27C5-494F-8121-3E5C82315DD5} + {0CA1DD2E-2752-4587-ADB4-77194411648B} = {C737AEEA-27C5-494F-8121-3E5C82315DD5} + {1295F70C-6CDC-4B99-AB85-5305CA8D7103} = {E7CF7E1E-CEAB-4015-BD70-7B2C727BD63E} + {47DF5C34-9275-4F92-8E87-B81B899EBA1F} = {E7CF7E1E-CEAB-4015-BD70-7B2C727BD63E} + {113E65CD-E297-4114-9C1B-0446A12D2EE1} = {1295F70C-6CDC-4B99-AB85-5305CA8D7103} + {208D8FE2-6A2C-438D-9CE9-CB4AAB6B33FD} = {47DF5C34-9275-4F92-8E87-B81B899EBA1F} + EndGlobalSection +EndGlobal diff --git a/Platform/Env.cs b/Platform/Env.cs new file mode 100644 index 0000000..ada570b --- /dev/null +++ b/Platform/Env.cs @@ -0,0 +1,247 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace Foo.Platform +{ + /// + /// Oogy Environment Class for getting OS, Application, and Theme Settings + /// + public class Env + { + private static int m_dwMajorVersion = 0; + private static int m_dwMinorVersion = 0; + private static Themes m_Theme = Themes.Classic; + private static AssemblyRunTimePath m_RunTimePath = null; + + /// + /// Public Properties + /// + public static int MajorVersion {get{return m_dwMajorVersion;}} + public static int MinorVersion {get{return m_dwMinorVersion;}} + public static Themes Theme {get{return m_Theme;}} + + /// + /// This is our versioning system, does not correspond to Windows + /// + public enum OSVersions : int + { + OS_WINDOWS_VISTA = 1, + OS_WINDOWS_2000 = 2, /*incl. Server OSes*/ + OS_WINDOWS_2003 = 3, /*incl. Server OSes and Windows XP*/ + OS_WINDOWS_SE7EN = 7, /*for future use ?*/ + OS_NOT_SUPPORTED = 99 + } + + /// + /// This are our Theme Configurations for ButtonHook/GUI components. + /// + public enum Themes : int + { + Classic = 0, + XPtheme = 1, + AeroTheme = 2, + VistaNoAero = 3 + } + + /// + /// Static Constructor, immediatly sets our environment variables + /// + static Env() + { + ObtainEnvInformation(); + m_RunTimePath = new AssemblyRunTimePath(); + } + + /// + /// Call this function first - before querying for themes, etc + /// + private static void ObtainEnvInformation() + { + GetSystemInformation(out m_dwMajorVersion, out m_dwMinorVersion); + CheckWindowsXPTheme(); + CheckWindowsVistaTheme(); + } + + /// + /// Use to get the Oogy Application path. Creates folder if none exists + /// + /// Path to Ooganizer Application Folder + public static string GetAppdirectory() + { + string appDataFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData); + string oogyAppData = appDataFolder + @"\Ooganizer"; + + if (!Directory.Exists(oogyAppData)) + { + // create oogy app data folder + Directory.CreateDirectory(oogyAppData); + } + + return oogyAppData; + } + + /// + /// Use to get the Oogy artifact snapshot image path. Creates folder if none exists + /// + /// Path to Ooganizer artifact snapshot data folder + public static string GetSnapshotDirectory() + { + string path = Platform.Env.GetAppdirectory() + @"\Snapshots"; + + if (!Directory.Exists(path)) + { + // create snapshot data folder + Directory.CreateDirectory(path); + } + + return path; + } + + /// + /// Use to get the Oogy log path. Creates folder if none exists + /// + /// Path to Ooganizer log folder + public static string GetLogDirectory() + { + string path = Platform.Env.GetAppdirectory() + @"\Logs"; + + if (!Directory.Exists(path)) + { + // create snapshot data folder + Directory.CreateDirectory(path); + } + + return path; + } + + /// + /// Use this to query the current running assembly path + /// + /// Path of assembly location + public static string GetRunTimePath() + { + return m_RunTimePath.strPath; + } + + /// + /// Quickly Check if the current OS Environment is supported by Oogy + /// + /// true if it is supported, false otherwise + public static bool IsWindowsOSSupported() + { + OSVersions version = OSVersionCheck(); + + if ((version == OSVersions.OS_WINDOWS_2003) || + (version == OSVersions.OS_WINDOWS_VISTA) || + (version == OSVersions.OS_WINDOWS_SE7EN)) + { + return true; + } + else + { + return false; + } + } + + /// + /// Retrieves Windows OS specific information + /// + /// dwMajorVersion[out] + /// dwMinorVersion[out] + /// is32bitNT[out] = supports 32-bit Windows NT + /// true, if succesfully retrieved, false otherwise + private static void GetSystemInformation(out int dwMajorVersion, out int dwMinorVersion) + { + dwMajorVersion = System.Environment.OSVersion.Version.Major; + dwMinorVersion = System.Environment.OSVersion.Version.Minor; + } + + /// + /// Use this function to obtain the current OS version information + /// + /// Returns the Current OSVersion Enum of this Environment + private static OSVersions OSVersionCheck() + { + switch(m_dwMajorVersion) // we ignore minor version for now + { + case 4: // Windows 2000? + return (OSVersions.OS_WINDOWS_2000); + case 5: // Windows XP && Windows 2003 + return (OSVersions.OS_WINDOWS_2003); + case 6: + return (OSVersions.OS_WINDOWS_VISTA); + case 7: + return (OSVersions.OS_WINDOWS_SE7EN); + default: + return (OSVersions.OS_NOT_SUPPORTED); + } + } + + /// + /// Vista Specific Theme Checking is done here + /// + /// + private static void CheckWindowsVistaTheme() + { + if(OSVersionCheck() == OSVersions.OS_WINDOWS_VISTA) + { + bool bIsAero = false; + if(Win32.Win32Functions.DwmIsCompositionEnabled(ref bIsAero) < 0) + return; //Call Failed + + if (bIsAero) + m_Theme = Themes.AeroTheme; + else + m_Theme = Themes.VistaNoAero; + } + } + + /// + /// XP Specific Theme Checking is done here + /// + /// + private static void CheckWindowsXPTheme() + { + if (OSVersionCheck() == OSVersions.OS_WINDOWS_2003) + { + if (Win32.Win32Functions.IsAppThemed()) + m_Theme = Themes.XPtheme; + else + m_Theme = Themes.Classic; + } + } + } + + /// + /// Since we only can query the Assembly path by instantiation, + /// we have a class that handles it + /// + internal class AssemblyRunTimePath + { + public string strPath; + public AssemblyRunTimePath(){strPath = Path.GetDirectoryName(GetType().Assembly.Location);} + } + + /// + /// EnvironmentCCW is a wrapper around Env - specifically made to be non-static + /// as to be able to be called from COM (ButtonHook/C++ code can now use Environment as well + /// + [Guid("85E2E5F6-877F-4edd-B7D1-D52C431F0AFC")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class EnvironmentCCW + { + public bool IsWindowsOSSupported() + { + return Env.IsWindowsOSSupported(); + } + public int GetCurWindowsTheme() + { + return (int)Env.Theme; + } + } + +} diff --git a/Platform/ErrorReporting/UserError.cs b/Platform/ErrorReporting/UserError.cs new file mode 100644 index 0000000..64a903b --- /dev/null +++ b/Platform/ErrorReporting/UserError.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +namespace Foo.Platform.ErrorReporting +{ + public class UserError + { + /// + /// Display an Error to the User + /// + /// Error Title + /// Any Details about the Error that maybe pertinent to the User + public static void Show(string title, string detail) + { + string strTitle = "Error - " + title; + string strDetail = detail + "\n\n\nContact Ooganizer Support at http://ooganizer.com/support for more help and information."; + + MessageBox.Show(strDetail,strTitle); + } + + } +} diff --git a/Platform/InstallationSpec.cs b/Platform/InstallationSpec.cs new file mode 100644 index 0000000..5d7ac04 --- /dev/null +++ b/Platform/InstallationSpec.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Win32; +using System.Reflection; + +namespace Foo.Platform +{ + /// + /// Installation Specific Settings. "HKLM\Software\Ooganizer", + /// The Installer must put the correct values in there so that we know where our files + /// are. ~Since now some of our assemblies are in the GAC, we require this. + /// + public class InstallationSpec + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// private statics + /// + private static string m_strInstallPath = ""; + //private static string m_strPlatformPath = ""; + //private static string m_strServerPath = ""; + //private static string m_strLogPath = ""; + private static RegistryKey s_OogyRootKey; + + /// + /// Public Properties + /// + public static string InstallPath { get { return m_strInstallPath; } } + //public static string PlatformPath { get { return m_strPlatformPath; } } + //public static string ServerPath { get { return m_strServerPath; } } + //public static string LogPath { get { return m_strLogPath; } } + + /// + /// Static Constructor, immediatly gets our installation specific variables + /// + static InstallationSpec() + { + s_OogyRootKey = Registry.LocalMachine.OpenSubKey("Software\\Ooganizer",false); + if (s_OogyRootKey != null) + { + object keyvalue = null; + + keyvalue = s_OogyRootKey.GetValue("InstallPath"); + if (isValidStr(keyvalue)) + m_strInstallPath = keyvalue.ToString(); + + //keyvalue = s_OogyRootKey.GetValue("PlatformPath"); + //if (isValidStr(keyvalue)) + // m_strPlatformPath = keyvalue.ToString(); + + //keyvalue = s_OogyRootKey.GetValue("ServerPath"); + //if (isValidStr(keyvalue)) + // m_strServerPath = keyvalue.ToString(); + + //keyvalue = s_OogyRootKey.GetValue("LogPath"); + //if (isValidStr(keyvalue)) + // m_strLogPath = keyvalue.ToString(); + } + else + { + Log.Error(string.Format("{0}() - Couldn't Open Software\\Ooganizer Registry Key for Reading", MethodBase.GetCurrentMethod().Name)); + } + } + + /// Returns true if passed in object is valid and not "" + private static bool isValidStr(object oToValidate) + { + if ((oToValidate != null) && (oToValidate.ToString() != "")) + return true; + else + return false; + } + } + + /// + /// Use this class for Debug Specific Settings + /// + public class DebugSpec + { + public static bool SkipCaptionButtonStarter { get; private set; } + + private static RegistryKey s_DebugSpecRootKey; + + static DebugSpec() + { + SkipCaptionButtonStarter = false; + + #if DEBUG + s_DebugSpecRootKey = Registry.LocalMachine.CreateSubKey("Software\\Ooganizer\\DebugSpec", RegistryKeyPermissionCheck.ReadWriteSubTree); + SkipCaptionButtonStarter = GetValB("SkipCaptionButtonStarter"); + #endif + } + + private static bool GetValB(string strValKey) + { + try + { + string val = GetVal(strValKey); + if (!String.IsNullOrEmpty(val)) + { + bool bVal = Boolean.Parse(val); + return bVal; + } + } + catch (Exception) { /* ignore */ } + return false; + } + + private static string GetVal(string strValKey) + { + try + { + object keyvalue = null; + keyvalue = s_DebugSpecRootKey.GetValue(strValKey); + if (isValidStr(keyvalue)) + return keyvalue.ToString(); + } + catch (Exception) { } + return String.Empty; + } + + /// Returns true if passed in object is valid and not "" + private static bool isValidStr(object oToValidate) + { + if ((oToValidate != null) && (oToValidate.ToString() != "")) + return true; + else + return false; + } + } + + /// + /// Temporary Values / "HKLM\Software\Ooganizer\TemporaryVal", + /// This class is being used to temporarily store values in the registry and retrieve them. + /// Useful for quick and dirty inter process communication. works out well for certain things. + /// + public class TemporaryVal + { + private static RegistryKey s_OogyRootKey; + + static TemporaryVal() + { + s_OogyRootKey = Registry.LocalMachine.OpenSubKey("Software\\Ooganizer", true); + } + + public static void SetVal(string strValue) + { + try { s_OogyRootKey.SetValue("TemporaryVal", strValue); } + catch (Exception) { } + } + + public static void SetValI(int iValue) + { + try{ SetVal(iValue.ToString()); } + catch (Exception){} + } + + public static string GetVal() + { + try + { + object keyvalue = null; + keyvalue = s_OogyRootKey.GetValue("TemporaryVal"); + if (isValidStr(keyvalue)) + return keyvalue.ToString(); + } + catch (Exception) { } + return String.Empty; + } + + public static int GetValI() + { + int I = 0; + try + { + string strVal = GetVal(); + I = int.Parse(strVal); + } + catch (Exception) { } + return I; + } + + public static void DeleteVal() + { + try { s_OogyRootKey.DeleteValue("TemporaryVal"); } + catch (Exception) { } + } + + /// Returns true if passed in object is valid and not "" + private static bool isValidStr(object oToValidate) + { + if ((oToValidate != null) && (oToValidate.ToString() != "")) + return true; + else + return false; + } + } +} diff --git a/Platform/Interacters/BHInteracter.cs b/Platform/Interacters/BHInteracter.cs new file mode 100644 index 0000000..e765075 --- /dev/null +++ b/Platform/Interacters/BHInteracter.cs @@ -0,0 +1,489 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Threading; + +namespace Foo.Platform.Interacters +{ + /// + /// BHInteracter - ButtonHook Interacter. + /// Use this class abstraction to send/communicate with ButtonHook. + /// + public class BHInteracter + { + //// + // Our ButtonHook.Dll Entry Points (Delegates) + //// + internal delegate bool MyStartButtonHook(); + internal static MyStartButtonHook _MyStartButtonHook = null; + + internal delegate bool MyStopButtonHook(); + internal static MyStopButtonHook _MyStopButtonHook = null; + + internal delegate bool MyIsButtonHookSet(); + internal static MyIsButtonHookSet _MyIsButtonHookSet = null; + + internal delegate int MyGetAllHookedWindowHandles(IntPtr pBuf); + internal static MyGetAllHookedWindowHandles _MyGetAllHookedWindowHandles = null; + + /// + /// Use this to send down to Buttonhook so that it knows what to show + /// + public enum BUTTON_HOOK_STATE + { + BUTTON_NONE = 1, + BUTTON_ADD = 2, + BUTTON_DELETE = 3 + } + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + //// + // Custom ButtonHook Message Handlers + //// + private const int WM_W32PINGISALIVE = (Platform.Win32.Win32_Constants.WM_USER + 700); + private const int WM_W32SETBUTTONSTATE = (Platform.Win32.Win32_Constants.WM_USER + 701); + private const int WM_W32GETBUTTONSTATE = (Platform.Win32.Win32_Constants.WM_USER + 702); + private const int WM_W32SETPARENTWINDOWTRANSPERANCY = (Platform.Win32.Win32_Constants.WM_USER + 703); + private const int WM_W32SETPARENTWINDOWACTIVE = (Platform.Win32.Win32_Constants.WM_USER + 704); + private const int WM_W32POSTMESSAGETOPARENTWINDOW = (Platform.Win32.Win32_Constants.WM_USER + 705); + + //// + // Custom OogyCaptionButton Message Handlers + //// + public const int WM_CAPTIONBUTTON_START = (Platform.Win32.Win32_Constants.WM_USER + 1200); + public const int WM_CAPTIONBUTTON_STOP = (Platform.Win32.Win32_Constants.WM_USER + 1201); + + //// + // OogyCaptionButton Spec + //// + private const int CAPTION_START_STOP_MAX_TRY_COUNT = 5; + public const string CAPTIONBUTTON_CMDLINE = @"/App:StartThis4Real639"; + private const string CAPTIONBUTTON_PROCESSNAME = "CaptionButton"; + private static string CAPTIONBUTTON_EXE = CAPTIONBUTTON_PROCESSNAME + ".exe"; + private static string CAPTIONBUTTON_EXE_FULLPATH = InstallationSpec.InstallPath + CAPTIONBUTTON_EXE; + private static IntPtr s_CaptionButtonHandle = IntPtr.Zero; + + /// + /// Validity internal State checking for OogyCaptionButton.exe + /// + private enum CAPTIONBUTTON_VALIDITY_STATE + { + VALIDITY_NONE = 1, + VALIDITY_CREATEDSUCCESS = 2, + VALIDITY_CREATEDFAILED = 3, + VALIDITY_STOPPEDSUCCESS = 4, + VALIDITY_STOPPEDFAILED = 5, + VALIDITY_INTEGRITYCHECK_FAILED = 6 + } + + // State Success / Error Checking + private static CAPTIONBUTTON_VALIDITY_STATE s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_NONE; + + /// + /// Static Constructor Loads the ButtonHook.dll dynamically from the correct path + /// + static BHInteracter() + { + try + { + IntPtr procaddr = IntPtr.Zero; + string strButtonHookDll = InstallationSpec.InstallPath + "ButtonHook.dll"; + + Log.Info(string.Format("{0}() - BHInteracter() Trying to load ButtonHook.dll {1}", MethodBase.GetCurrentMethod().Name, strButtonHookDll)); + IntPtr ButtonHook = Win32.Win32Functions.LoadLibrary(strButtonHookDll); + if(ButtonHook != IntPtr.Zero) + Log.Info(string.Format("{0}() - BHInteracter() loading ButtonHook.dll succeeded", MethodBase.GetCurrentMethod().Name)); + else + Log.Error(string.Format("{0}() - BHInteracter() loading ButtonHook.dll failed!", MethodBase.GetCurrentMethod().Name)); + + // StartButtonHook + procaddr = Win32.Win32Functions.GetProcAddress(ButtonHook, "_StartButtonHook@0"); + if(procaddr != null) + _MyStartButtonHook = (MyStartButtonHook)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(MyStartButtonHook)); + else + Log.Info(string.Format("{0}() - BHInteracter() GetProcAddress for StartButtonHook Failed", MethodBase.GetCurrentMethod().Name)); + + // StopButtonHook + procaddr = Win32.Win32Functions.GetProcAddress(ButtonHook, "_StopButtonHook@0"); + if (procaddr != null) + _MyStopButtonHook = (MyStopButtonHook)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(MyStopButtonHook)); + else + Log.Info(string.Format("{0}() - BHInteracter() GetProcAddress for StopButtonHook Failed", MethodBase.GetCurrentMethod().Name)); + + // IsButtonHookSet + procaddr = Win32.Win32Functions.GetProcAddress(ButtonHook, "_IsButtonHookSet@0"); + if (procaddr != null) + _MyIsButtonHookSet = (MyIsButtonHookSet)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(MyIsButtonHookSet)); + else + Log.Info(string.Format("{0}() - BHInteracter() GetProcAddress for IsButtonHookSet Failed", MethodBase.GetCurrentMethod().Name)); + + // GetAllHookedWindowHandles + procaddr = Win32.Win32Functions.GetProcAddress(ButtonHook, "_GetAllHookedWindowHandles@4"); + if (procaddr != null) + _MyGetAllHookedWindowHandles = (MyGetAllHookedWindowHandles)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(MyGetAllHookedWindowHandles)); + else + Log.Info(string.Format("{0}() - BHInteracter() GetProcAddress for GetAllHookedWindowHandles Failed", MethodBase.GetCurrentMethod().Name)); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - BHInteracter() Construction Failed", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// Use this function wrapper to call the StartButtonHook DLLEntry Point + /// + public static void StartButtonHookDLLEntryW() + { + Log.Info(string.Format("{0}() - CaptionButton - About to call StartButtonHook()", MethodBase.GetCurrentMethod().Name)); + if (_MyStartButtonHook()) + Log.Info(string.Format("{0}() - StartButtonHook() Succeeded", MethodBase.GetCurrentMethod().Name)); + else + Log.Error(string.Format("{0}() - StartButtonHook() Failed", MethodBase.GetCurrentMethod().Name)); + } + + /// + /// Use this function wrapper to call the StopButtonHook DLLEntry Point + /// + public static void StopButtonHookDLLEntryW() + { + Log.Info(string.Format("{0}() - CaptionButton - About to call StopButtonHook()", MethodBase.GetCurrentMethod().Name)); + if (_MyStopButtonHook()) + Log.Info(string.Format("{0}() - StopButtonHook() Succeeded", MethodBase.GetCurrentMethod().Name)); + else + Log.Error(string.Format("{0}() - StopButtonHook() Failed", MethodBase.GetCurrentMethod().Name)); + } + + /// + /// Use this function wrapper to call the IsButtonHookSet DLLEntry Point + /// + public static bool IsButtonHookSetDLLEntryW() + { + return _MyIsButtonHookSet(); + } + + /// + /// Use this function wrapper to call the GetAllHookedWindowHandles DLLEntry Point + /// + public static void GetAllHookedWindowHandlesDLLEntryW(ref List handleList) + { + // Temporary ar buffer + int[] ar = new int[Win32.Win32_Constants.MAX_PATH]; + + // allocate and reset an new unmanaged buffer + IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(ar)); + Marshal.Copy(ar, 0, p, ar.Length); + + // get the size + int nsize = _MyGetAllHookedWindowHandles(p); + + // copy data back as needed *delete unmanaged buffer* + Marshal.Copy(p,ar,0,nsize); + Marshal.FreeHGlobal(p); + + // Make sure the passed in list is empty * and pass out the handle list* + handleList.Clear(); + for (int i = 0; i < nsize; ++i) + handleList.Add((IntPtr)ar[i]); + } + + /// + /// CaptionButton exe is the external process that hosts ButtonHook.dll + /// + /// true if the CaptionButtion exe is running, false otherwise + public static bool IsCaptionButtonRunning() + { + Process[] processes = Process.GetProcessesByName(CAPTIONBUTTON_PROCESSNAME); + return (processes.Length == 1); + } + + /// + /// Start CaptionButton exe which can host the ButtonHook.dll + /// + public static void StartCaptionButton() + { + try + { + if (!IsCaptionButtonRunning()) + { + TemporaryVal.DeleteVal(); + ProcessStartInfo startInfo = new ProcessStartInfo(CAPTIONBUTTON_EXE_FULLPATH, CAPTIONBUTTON_CMDLINE); + startInfo.WindowStyle = ProcessWindowStyle.Hidden; + startInfo.WorkingDirectory = InstallationSpec.InstallPath; + Process p = Process.Start(startInfo); + Log.Info(string.Format("{0}() - Created a new Oogy CaptionButton Instance EXE with PID{1}", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + + // Wait a little before sending any messages + Thread.Sleep(3000); + + //// + // State Checking *IMP* .exe could have not shut down correctly, and buttonhook never got stopped + // so let's check to see what is going on + //// + bool bIsInvalidState = ((s_CaptionButtonState != CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_NONE) && + (s_CaptionButtonState != CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_STOPPEDSUCCESS)); + + // Let's get the window handle from the child process + s_CaptionButtonHandle = (IntPtr)TemporaryVal.GetValI(); + if (s_CaptionButtonHandle == IntPtr.Zero) + Log.Error(string.Format("{0}() - Child Handle is Zero! This means all functions below will return out and everything fails. Check into this.", MethodBase.GetCurrentMethod().Name)); + + TemporaryVal.DeleteVal(); + + // We somehow got into an invalid state, so let's send Stop Messages and see what happens, + // if those failed there is really not much more we can do except fail here + if (bIsInvalidState && !Helper_CaptionButtonMessageSender(s_CaptionButtonHandle, WM_CAPTIONBUTTON_STOP)) + Log.Info(string.Format("{0}() - Trying to StopButtonHook gracefully failed - ignoring and trying to StartButtonHook Anyways", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + + // Regular starting... + if (Helper_CaptionButtonMessageSender(s_CaptionButtonHandle, WM_CAPTIONBUTTON_START)) + { + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_CREATEDSUCCESS; + Log.Info(string.Format("{0}() - StartCaptionButton Succeeded - Started the ButtonHook Worked Successfully", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + } + else + { + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_CREATEDFAILED; + Log.Error(string.Format("{0}() - StartCaptionButton Failed - Started the ButtonHook Did not work - VALIDITY_CREATEDFAILED - forcefully Killing the Process", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + p.Kill(); + } + } + else + { + // Process is already running for some reason - this should never happen, but if it does, + // we'll handle it by doing an integrity check + Log.Info(string.Format("{0}() - StartCaptionButton - CaptionButton.exe already exists - performing Complete Integrity Check...", MethodBase.GetCurrentMethod().Name)); + bool bIntegrityIsGood = CompleteButtonHookIntegrityCheck(); + + if (bIntegrityIsGood) + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_CREATEDSUCCESS; + else + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_INTEGRITYCHECK_FAILED; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - StartCaptionButton - Error occured", MethodBase.GetCurrentMethod().Name), e); + } + } + + /// + /// Stop CaptionButton exe which can host the ButtonHook.dll + /// + public static void StopCaptionButton() + { + Log.Info(string.Format("{0}() - StopCaptionButton Called", MethodBase.GetCurrentMethod().Name)); + if (IsCaptionButtonRunning()) + { + Process[] processes = Process.GetProcessesByName(CAPTIONBUTTON_PROCESSNAME); + foreach (Process p in processes) + { + Log.Info(string.Format("{0}() - Found OogyCaptionButton Pid {1}", MethodBase.GetCurrentMethod().Name, p.Id)); + + if (Helper_CaptionButtonMessageSender(s_CaptionButtonHandle, WM_CAPTIONBUTTON_STOP)) + { + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_STOPPEDSUCCESS; + Log.Info(string.Format("{0}() - StopCaptionButton Succeeded - Closing the ButtonHook Worked Successfully", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + } + else + { + s_CaptionButtonState = CAPTIONBUTTON_VALIDITY_STATE.VALIDITY_STOPPEDFAILED; + Log.Error(string.Format("{0}() - StopCaptionButton Failed - Closing the ButtonHook Did not work - forcefully Killing the Process", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + } + + Log.Info(string.Format("{0}() - Closing a Oogy CaptionButton Instance EXE of PID{1}", MethodBase.GetCurrentMethod().Name, p.Id.ToString())); + p.Kill(); + } + } + } + + /// + /// Use this to send the Start/Stop Messages to Oogy CaptionButton.exe. Small Helper + /// function allows us to do cleaner error handling for starting and stopping (above) + /// + /// WM_CAPTIONBUTTON_START or WM_CAPTIONBUTTON_STOP + /// returns true if successful, false otherwise + private static bool Helper_CaptionButtonMessageSender(IntPtr hWnd, int Message) + { + if((hWnd != IntPtr.Zero) && + (Message == WM_CAPTIONBUTTON_START || Message == WM_CAPTIONBUTTON_STOP)) + { + for (int i = 0; i < CAPTION_START_STOP_MAX_TRY_COUNT; ++i) + { + // Send the Stop ButonHook Message to the Hidden window of the Process + Win32.Win32Functions.SendMessage(hWnd, Message, IntPtr.Zero, IntPtr.Zero); + + // Wait a little second before querying for the state + Thread.Sleep(500); + + // If this is a start message we can stop once the button hook is started + if (Message == WM_CAPTIONBUTTON_START && + IsButtonHookSetDLLEntryW()) + return true; + + // If this is a stop message we can stop once the button hook no longer set + if (Message == WM_CAPTIONBUTTON_STOP && + !IsButtonHookSetDLLEntryW()) + return true; + } + } + return false; + } + + /// + /// Check to see if buttonhook is alive for the passed in window + /// + /// handle to a buttonHooked Parent Window + public static bool IsButtonHookAliveOnWindow(IntPtr hWnd) + { + if (hWnd != IntPtr.Zero) + { + int retVal = Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32PINGISALIVE, IntPtr.Zero, IntPtr.Zero); + if (retVal == 0) + { + Log.Error(string.Format("{0}() - IsButtonHookAlive Failed for Window {1}", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + return false; + } + else + { + return true; + } + } + return false; + } + + /// + /// Call this function to run a complete ButtonHook Integrity Check + /// + /// true if buttonhook passed all checks, false otherwise + public static bool CompleteButtonHookIntegrityCheck() + { + bool bSuccess = true; + Log.Info(string.Format("{0}() - CompleteButtonHookIntegrityCheck got called", MethodBase.GetCurrentMethod().Name)); + + // Make first sure that the Hook Is Set + if (!IsButtonHookSetDLLEntryW()) + bSuccess = false; + + // Now iterate through each hooked window pinging it + // for feedback + List handleList = new List(); + foreach (IntPtr hWnd in handleList) + { + if (!IsButtonHookAliveOnWindow(hWnd) && Win32.Win32Functions.IsWindow(hWnd)) + { + bSuccess = false; // buttonhook not responsive on an existing window + break; + } + } + + if(bSuccess) + Log.Info(string.Format("{0}() - CompleteButtonHookIntegrityCheck passed successfully", MethodBase.GetCurrentMethod().Name)); + else + Log.Error(string.Format("{0}() - CompleteButtonHookIntegrityCheck failed", MethodBase.GetCurrentMethod().Name)); + + return bSuccess; + } + + /// + /// Use this to set the Transparency on a Window that is running the ButtonHook. ~Will Only work + /// for those windows. + /// + /// handle to a buttonHooked Parent Window + /// 0-255 byte value indicating the Transparency + public static void SetWindowTransparency(IntPtr hWnd, byte alpha) + { + if (hWnd != IntPtr.Zero) + { + int retVal = Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32SETPARENTWINDOWTRANSPERANCY, IntPtr.Zero, (IntPtr)alpha); + if (retVal == 0) + Log.Error(string.Format("{0}() - SetWindowTransparency Failed for Window {1} with alpha {2}", MethodBase.GetCurrentMethod().Name, hWnd.ToString(), alpha.ToString())); + } + } + + /// + /// Use this to set the ActiveWindow on a Window that is running the ButtonHook. ~Will Only work + /// for those windows. + /// + /// handle to a buttonHooked Parent Window + public static void SetAsActiveWindow(IntPtr hWnd) + { + if (hWnd != IntPtr.Zero) + { + int retVal = Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32SETPARENTWINDOWACTIVE, IntPtr.Zero, IntPtr.Zero); + if (retVal == 0) + Log.Error(string.Format("{0}() - SetAsActiveWindow Failed for Window {1}", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + } + } + + /// + /// Use this to send a message to a window to send a message to itself + /// + /// + public static void PostMessageAsIfFromWindow(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam ) + { + if (hWnd != IntPtr.Zero) + { + StringBuilder strAtom = new StringBuilder(hWnd.ToString() + ";" + Msg.ToString() + ";" + wParam.ToString() + ";" + lParam.ToString()); + int nAtom = Win32.Win32Functions.GlobalAddAtom(strAtom); + + if (nAtom == 0) + Log.Error(string.Format("{0}() - SendMessageAsIfFromWindow GlobalAddAtom Failed for Window {1}", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + + int retVal = Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32POSTMESSAGETOPARENTWINDOW, IntPtr.Zero, (IntPtr)nAtom); + if (retVal == 0) + Log.Error(string.Format("{0}() - SendMessageAsIfFromWindow ButtonHook Failed to process the String for Window {1}", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + + Win32.Win32Functions.GlobalDeleteAtom(nAtom); + } + } + + /// + /// Use this to set a new ButtonState to a buttonhooked window + /// + /// handle to a buttonHooked Parent Window + /// a new button state + public static BUTTON_HOOK_STATE SetW32ButtonToNewState(IntPtr hWnd, BUTTON_HOOK_STATE buttonState) + { + if (hWnd != IntPtr.Zero) + { + int retVal = Platform.Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32SETBUTTONSTATE, IntPtr.Zero, (IntPtr)buttonState); + if (retVal == 0) + Log.Error(string.Format("{0}() - SetW32ButtonToNewState Failed for Window {1} ", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + } + return buttonState; + } + + /// + /// Use this to get a ButtonState from a buttonhooked window + /// + /// handle to a buttonHooked Parent Window + /// a new button state + public static BUTTON_HOOK_STATE GetW32ButtonState(IntPtr hWnd) + { + BUTTON_HOOK_STATE buttonState = BUTTON_HOOK_STATE.BUTTON_NONE; + if (hWnd != IntPtr.Zero) + { + int retVal = Platform.Win32.Win32Functions.SendMessage((IntPtr)hWnd, WM_W32GETBUTTONSTATE, IntPtr.Zero, IntPtr.Zero); + if (retVal == 0) + Log.Error(string.Format("{0}() - SetW32ButtonToNewState Failed for Window {1} ", MethodBase.GetCurrentMethod().Name, hWnd.ToString())); + + try + { + buttonState = (BUTTON_HOOK_STATE)retVal; + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - Error Thrown ", MethodBase.GetCurrentMethod().Name), e); + } + } + return buttonState; + } + + } +} diff --git a/Platform/Logger.cs b/Platform/Logger.cs new file mode 100644 index 0000000..4d1b906 --- /dev/null +++ b/Platform/Logger.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using log4net.Config; +using log4net.Core; +using log4net.Appender; +using log4net.Layout; +using log4net.Repository.Hierarchy; + +namespace Foo.Platform +{ + public class Logger + { + static Logger() + { + BasicConfigurator.Configure(CreateAndConfigureRollingFileAppender()); + } + + /// + /// Returns the Log4Net Interface + /// + /// Object Type to pass in to create Logger for + /// Log4Net Interface + public static ILog GetLog4NetInterface(Type type) + { + return LogManager.GetLogger(type); + } + + /// + /// Creates and Configures teh RollingFileAppender *Configuration goes on here * + /// + /// RollingFileAppender Class to be used in Configuring Log4Net + static private RollingFileAppender CreateAndConfigureRollingFileAppender() + { + RollingFileAppender fileAppender = new RollingFileAppender(); + fileAppender.Layout = new PatternLayout(PatternLayout.DetailConversionPattern); + + // Locking Minimal allows us to run Log4Net from multiple processes + fileAppender.LockingModel = new FileAppender.MinimalLock(); + + fileAppender.File = (Env.GetLogDirectory() + @"\LogServer.log"); + fileAppender.AppendToFile = true; + + #if DEBUG + fileAppender.Threshold = Level.All; + #else + fileAppender.Threshold = Level.Error; + #endif + + fileAppender.MaximumFileSize = "5MB"; + fileAppender.MaxSizeRollBackups = 3; + fileAppender.ActivateOptions(); + return fileAppender; + } + + } +} diff --git a/Platform/MyKeyFile.SNK b/Platform/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Platform/MyKeyFile.SNK differ diff --git a/Platform/OSWrapper.cs b/Platform/OSWrapper.cs new file mode 100644 index 0000000..e6bba38 --- /dev/null +++ b/Platform/OSWrapper.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ooganizer.Platform +{ + class OSWrapper + { + + + void Lalelu() + { + using (OoganizerState oogyState = new OoganizerState()) + { + string curWorkspaceName = oogyState.GetCurrentWorkspace(); + + if (curWorkspaceName != null) + { + using (OoganizerAPIProxy proxy = oogyState.GetAPIProxy()) + { + Workspace curWorkspace = proxy.API.GetWorkspace(curWorkspaceName); + + foreach (OoganizerDAL.Artifact artifact in curWorkspace.Artifacts) + { + if (curArtifact.Location.ToUpper() == artifact.Location.ToUpper()) + { + bFound = true; + break; + } + } + } + } + } + } + + + + } +} diff --git a/Platform/ObjectPooling.txt b/Platform/ObjectPooling.txt new file mode 100644 index 0000000..d259d25 --- /dev/null +++ b/Platform/ObjectPooling.txt @@ -0,0 +1,3 @@ + +Enterprise Services (.NET 1.1) Performance Guidelines - Object Pooling +http://www.guidanceshare.com/wiki/Enterprise_Services_(.NET_1.1)_Performance_Guidelines_-_Object_Pooling \ No newline at end of file diff --git a/Platform/Platform.csproj b/Platform/Platform.csproj new file mode 100644 index 0000000..4842e92 --- /dev/null +++ b/Platform/Platform.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Library + Properties + Foo.Platform + Platform + v3.5 + 512 + + + + + + + + + + + true + MyKeyFile.SNK + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + False + ..\Components\log4net.dll + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16} + Satellite + + + + + + $(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /unregister +$(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /tlb:$(TargetName).tlb /codebase +mkdir "$(SolutionDir)target\$(ConfigurationName)\Resources" +xcopy "$(ProjectDir)Resources" "$(SolutionDir)target\$(ConfigurationName)\Resources" /E /C /Y +copy "$(SolutionDir)Components\log4net.dll" "$(SolutionDir)target\$(ConfigurationName)\log4net.dll" /Y + + + + \ No newline at end of file diff --git a/Platform/Properties/AssemblyInfo.cs b/Platform/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..86debdf --- /dev/null +++ b/Platform/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Platform")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Platform")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7401c7a2-13c4-4821-9b09-deb707d27b3a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Platform/Resources/Themes/AeroTheme/ButtonDown.ico b/Platform/Resources/Themes/AeroTheme/ButtonDown.ico new file mode 100644 index 0000000..bfc3922 Binary files /dev/null and b/Platform/Resources/Themes/AeroTheme/ButtonDown.ico differ diff --git a/Platform/Resources/Themes/AeroTheme/ButtonUp.ico b/Platform/Resources/Themes/AeroTheme/ButtonUp.ico new file mode 100644 index 0000000..eae7472 Binary files /dev/null and b/Platform/Resources/Themes/AeroTheme/ButtonUp.ico differ diff --git a/Platform/Resources/Themes/AeroTheme/ToggleUp.ico b/Platform/Resources/Themes/AeroTheme/ToggleUp.ico new file mode 100644 index 0000000..95056b1 Binary files /dev/null and b/Platform/Resources/Themes/AeroTheme/ToggleUp.ico differ diff --git a/Platform/Resources/Themes/ClassicTheme/ButtonDown.ico b/Platform/Resources/Themes/ClassicTheme/ButtonDown.ico new file mode 100644 index 0000000..e944d27 Binary files /dev/null and b/Platform/Resources/Themes/ClassicTheme/ButtonDown.ico differ diff --git a/Platform/Resources/Themes/ClassicTheme/ButtonUp.ico b/Platform/Resources/Themes/ClassicTheme/ButtonUp.ico new file mode 100644 index 0000000..516f4e8 Binary files /dev/null and b/Platform/Resources/Themes/ClassicTheme/ButtonUp.ico differ diff --git a/Platform/Resources/Themes/ClassicTheme/ToggleUp.ico b/Platform/Resources/Themes/ClassicTheme/ToggleUp.ico new file mode 100644 index 0000000..6b801ae Binary files /dev/null and b/Platform/Resources/Themes/ClassicTheme/ToggleUp.ico differ diff --git a/Platform/Resources/Themes/VistaNoAeroTheme/ButtonDown.ico b/Platform/Resources/Themes/VistaNoAeroTheme/ButtonDown.ico new file mode 100644 index 0000000..e944d27 Binary files /dev/null and b/Platform/Resources/Themes/VistaNoAeroTheme/ButtonDown.ico differ diff --git a/Platform/Resources/Themes/VistaNoAeroTheme/ButtonUp.ico b/Platform/Resources/Themes/VistaNoAeroTheme/ButtonUp.ico new file mode 100644 index 0000000..516f4e8 Binary files /dev/null and b/Platform/Resources/Themes/VistaNoAeroTheme/ButtonUp.ico differ diff --git a/Platform/Resources/Themes/VistaNoAeroTheme/ToggleUp.ico b/Platform/Resources/Themes/VistaNoAeroTheme/ToggleUp.ico new file mode 100644 index 0000000..6b801ae Binary files /dev/null and b/Platform/Resources/Themes/VistaNoAeroTheme/ToggleUp.ico differ diff --git a/Platform/Resources/Themes/XPTheme/ButtonDown.ico b/Platform/Resources/Themes/XPTheme/ButtonDown.ico new file mode 100644 index 0000000..e944d27 Binary files /dev/null and b/Platform/Resources/Themes/XPTheme/ButtonDown.ico differ diff --git a/Platform/Resources/Themes/XPTheme/ButtonUp.ico b/Platform/Resources/Themes/XPTheme/ButtonUp.ico new file mode 100644 index 0000000..516f4e8 Binary files /dev/null and b/Platform/Resources/Themes/XPTheme/ButtonUp.ico differ diff --git a/Platform/Resources/Themes/XPTheme/ToggleUp.ico b/Platform/Resources/Themes/XPTheme/ToggleUp.ico new file mode 100644 index 0000000..6b801ae Binary files /dev/null and b/Platform/Resources/Themes/XPTheme/ToggleUp.ico differ diff --git a/Platform/Satellite/GUI.cs b/Platform/Satellite/GUI.cs new file mode 100644 index 0000000..d5ee080 --- /dev/null +++ b/Platform/Satellite/GUI.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Resources; +using System.Reflection; + +namespace Foo.Platform.Satellite +{ + /// + /// Quick N' Easy access to the Satellite GUI Assembly Resource + /// + public static class GUIResx + { + private static ResourceManager _ResourceManager = null; + private static Assembly _Assembly = null; + + /// + /// Construction + /// + static GUIResx() + { + try + { + if (_ResourceManager == null && _Assembly == null) + { + _Assembly = Assembly.LoadFile(InstallationSpec.InstallPath + "\\" + "Satellite.dll"); + _ResourceManager = new ResourceManager("Foo.Satellite.GUI", _Assembly); + + // * For Debugging * + //string[] resourceNames = _Assembly.GetManifestResourceNames(); + //foreach (string resourceName in resourceNames) + //{ + // string Doris = resourceName; + //} + } + } + catch (Exception e) + { + string message = e.Message; + } + } + + /// + /// Returns a Resource value as a string + /// + /// name of resource to get + /// the value of the resource + public static string GetString(string strName) + { + string retVal = string.Empty; + try + { + retVal = _ResourceManager.GetString(strName); + } + catch (Exception e) + { + string message = e.Message; + } + return retVal; + } + } +} diff --git a/Platform/Utilities/DebugLogger.cs b/Platform/Utilities/DebugLogger.cs new file mode 100644 index 0000000..f58e99b --- /dev/null +++ b/Platform/Utilities/DebugLogger.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using Microsoft.Win32; +using System.Reflection; +using System.Diagnostics; + +namespace Ooganizer.Platform.Utilities +{ + public class DebugLogger + { + private static string s_strFileNPath = ""; + private static FileM s_fileM = null; + private static LogInstantiator s_LogI = null; + private static int s_LoadTime = 0; + private static bool s_firstTime = true; + + /// + /// Use the Log(string line) method to quickly write to a temp log file in the current assembly directory + /// + static DebugLogger() + { + if (s_LogI == null) + { + int timebefore = System.Environment.TickCount; + s_LogI = new LogInstantiator(); + s_LoadTime = System.Environment.TickCount - timebefore; + } + + if (s_fileM == null) + s_fileM = new FileM(s_LogI.strFileName, "log", s_LogI.strDirectoryPath, true); + + if(s_strFileNPath == "") + s_strFileNPath = s_fileM.PathNFile; + } + + public static void Log(string line) + { + if (s_firstTime) + { + //s_fileM.WriteLineUTF8("EasyLogger's Logger.cs was loaded in " + s_LoadTime.ToString() + " miliseconds"); + s_firstTime = false; + } + s_fileM.WriteLineUTF8(line); + } + + /// + /// Small Helper class in order to get the location of the currently running assembly + /// + private class LogInstantiator + { + public string strFileName; + public string strDirectoryPath; + private static RegistryKey s_OogyRootKey; + + public LogInstantiator() + { + // For Random File names ~shouldn't be used anymore + //string strRandomFileName = Path.GetRandomFileName(); + //strRandomFileName = strRandomFileName.Substring(0, (strRandomFileName.Length - 4)); // stripe extension (.xyz) + //strFileName = strRandomFileName; + + // Find the Calling Assembly that is NOT this one + StackTrace stackTrace = new StackTrace(); + StackFrame stackFrame; + MethodBase stackFrameMethod; + string typeName; + + int framecount = 3; + stackFrame = stackTrace.GetFrame(framecount); + stackFrameMethod = stackFrame.GetMethod(); + typeName = stackFrameMethod.ReflectedType.FullName; + + // *IMP* Use the calling Assembly Type Name as the file name + strFileName = typeName; + + // *Work-Around*, we can't have a circular reference with InstallationSpec, so we just + // have to Query for the LogPath Directly instead of using Platform.InstallationSpec + s_OogyRootKey = Registry.LocalMachine.OpenSubKey("Software\\Ooganizer",false); + + if (s_OogyRootKey != null) + { + object keyvalue = s_OogyRootKey.GetValue("LogPath"); + if ((keyvalue != null) && (keyvalue.ToString() != "")) + strDirectoryPath = keyvalue.ToString(); + } + } + } + } +} diff --git a/Platform/Utilities/FileM.cs b/Platform/Utilities/FileM.cs new file mode 100644 index 0000000..7d08be7 --- /dev/null +++ b/Platform/Utilities/FileM.cs @@ -0,0 +1,154 @@ + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace Ooganizer.Platform.Utilities +{ + public class FileM + { + private string m_sFileName; + private string m_sFileType; + private string m_sFileDirPath; + + //Flags + private bool m_bIsFileCreated = false; + private bool m_bOverideExisting = true; + private bool m_bDeleteOnDestruct = false; + + // Creates Temporary File by Default + public FileM(string FileType) + { + m_sFileName = Path.GetRandomFileName(); + m_sFileType = FileType; + m_sFileDirPath = Path.GetTempPath(); + m_bDeleteOnDestruct = true; + } + + public FileM(string FileType, bool bDontDeleteOnDestruct) + { + m_sFileName = Path.GetRandomFileName(); + m_sFileType = FileType; + m_sFileDirPath = Path.GetTempPath(); + m_bDeleteOnDestruct = !bDontDeleteOnDestruct; + } + + public FileM(string FileName, string FileType, string DirectoryPath, bool OverideExisting) + { + m_sFileName = FileName; + m_sFileType = FileType; + if (!Directory.Exists(DirectoryPath)) + { + Directory.CreateDirectory(DirectoryPath); + } + m_sFileDirPath = DirectoryPath + "\\"; + m_bOverideExisting = OverideExisting; + } + + ~FileM() + { + if (m_bDeleteOnDestruct) + { + File.Delete(this.PathNFile); + } + } + + public void WriteLineA(string line) + { + FileStream fs = CreateFile(); + StreamWriter sw = new StreamWriter(fs, Encoding.ASCII); + sw.WriteLine(line); + sw.Flush(); + sw.Close(); + fs.Close(); + } + + public void WriteLineA(string[] lines) + { + FileStream fs = CreateFile(); + StreamWriter sw = new StreamWriter(fs, Encoding.ASCII); + + foreach (string line in lines) + { + sw.WriteLine(line); + } + + sw.Flush(); + sw.Close(); + fs.Close(); + } + + public void WriteLineUTF8(string line) + { + FileStream fs = CreateFile(); + StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); + sw.WriteLine(line); + sw.Flush(); + sw.Close(); + fs.Close(); + } + + public void WriteLineUTF8(string[] lines) + { + FileStream fs = CreateFile(); + StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); + + foreach (string line in lines) + { + sw.WriteLine(line); + } + + sw.Flush(); + sw.Close(); + fs.Close(); + } + + public void DeleteIfExists() + { + if (File.Exists(this.PathNFile)) + { + File.Delete(this.PathNFile); + } + } + + private FileStream CreateFile() + { + if (!m_bIsFileCreated && m_bOverideExisting) + { + m_bIsFileCreated = true; + return (new FileStream(this.PathNFile, FileMode.Create)); + } + else + { + return (new FileStream(this.PathNFile, FileMode.Append)); + } + } + + // public properties + public string FileName + { + get + { + return (this.FileName); + } + } + + public string DirectoryPath + { + get + { + return (this.m_sFileDirPath); + } + } + + public string PathNFile + { + get + { + return (m_sFileDirPath + m_sFileName + "." + m_sFileType); + } + } + + } +} diff --git a/Platform/Utilities/RegM.cs b/Platform/Utilities/RegM.cs new file mode 100644 index 0000000..122bb65 --- /dev/null +++ b/Platform/Utilities/RegM.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Win32; + +namespace Foo.Platform.Utilities +{ + public enum HKEYRoot + { + ClassesRoot, + CurrentUser, + LocalMachine, + } + + public enum KeySub + { + Software, + Custom + } + + public class RegM + { + + private RegistryKey _RegKey; + + /// + /// Use this to Open/Automatically Create a Registry Key + /// + /// specify registry root + /// specify a sub or custom + /// key you want to open / create + /// true if you plan on writing to it + public RegM(HKEYRoot root, KeySub sub, string Key, bool bWrite) + { + string KeyToOpen = String.Empty; + if (sub == KeySub.Custom) + KeyToOpen = Key; + else + KeyToOpen = sub.ToString() + "\\" + Key; + + RegistryKeyPermissionCheck permission = RegistryKeyPermissionCheck.ReadSubTree; + if (bWrite) + permission = RegistryKeyPermissionCheck.ReadWriteSubTree; + + // Open/Create if it doesn't exist, the Proper Key + switch (root) + { + case HKEYRoot.ClassesRoot: + _RegKey = Registry.ClassesRoot.CreateSubKey(KeyToOpen, permission); + break; + + case HKEYRoot.CurrentUser: + _RegKey = Registry.CurrentUser.CreateSubKey(KeyToOpen, permission); + break; + + case HKEYRoot.LocalMachine: + _RegKey = Registry.LocalMachine.CreateSubKey(KeyToOpen, permission); + break; + } + } + + #region GetValue Registry Functions + + public bool GetVal_String(string strValKey, out string StringValue) + { + StringValue = String.Empty; + try + { + object keyvalue = null; + keyvalue = _RegKey.GetValue(strValKey); + if (isValidStr(keyvalue)) + StringValue = keyvalue.ToString(); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool GetVal_Bool(string strValKey, out bool BoolValue) + { + BoolValue = false; + try + { + string StringValue; + if (GetVal_String(strValKey, out StringValue) && + !String.IsNullOrEmpty(StringValue)) + BoolValue = Boolean.Parse(StringValue); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool GetVal_Int(string strValKey, out int IntValue) + { + IntValue = 0; + try + { + string StringValue; + if (GetVal_String(strValKey, out StringValue) && + !String.IsNullOrEmpty(StringValue)) + IntValue = int.Parse(StringValue); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool GetVal_Binary(string strValKey, out byte[] ByteValue) + { + ByteValue = null; + try + { + string StringValue; + if (GetVal_String(strValKey, out StringValue) && + !String.IsNullOrEmpty(StringValue)) + { + ByteValue = new Byte[StringValue.Length]; + for (int i = 0; i < ByteValue.Length; ++i) + { + string strByte = Convert.ToString(StringValue[i]); + ByteValue[i] = byte.Parse(strByte); + } + } + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + #endregion + + #region SetValue Registry Functions + + public bool SetVal_String(string strValKey, string StringValue) + { + try + { + _RegKey.SetValue(strValKey, StringValue, RegistryValueKind.String); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool SetVal_Bool(string strValKey, bool BoolValue) + { + try + { + _RegKey.SetValue(strValKey, BoolValue.ToString(), RegistryValueKind.String); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool SetVal_Int(string strValKey, int DwordValue) + { + try + { + _RegKey.SetValue(strValKey, DwordValue, RegistryValueKind.DWord); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + public bool SetVal_Binary(string strValKey, byte[] ByteValue) + { + try + { + _RegKey.SetValue(strValKey, ByteValue, RegistryValueKind.Binary); + return true; + } + catch (Exception) { /* ignore */ } + return false; + } + + #endregion + + /// Returns true if passed in object is valid and not "" + private bool isValidStr(object oToValidate) + { + if ((oToValidate != null) && (oToValidate.ToString() != "")) + return true; + else + return false; + } + } + +} diff --git a/Platform/Win32.cs b/Platform/Win32.cs new file mode 100644 index 0000000..0fe3a71 --- /dev/null +++ b/Platform/Win32.cs @@ -0,0 +1,1362 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Diagnostics; +using System.Threading; +using System.Windows.Forms; +using System.Drawing; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +// TODO Move most of this to the Platform project +namespace Foo.Platform.Win32 +{ + public class MyWin32Wnd : IWin32Window + { + private IntPtr m_Handle = IntPtr.Zero; + public IntPtr Handle + { + get{return m_Handle;} + set{m_Handle = value;} + } + } + + //// + // Win32 Enums + //// + #region Win32 Enums + + public enum WindowAction : int + { + SW_HIDE = 0, + SW_SHOWNORMAL = 1, + SW_NORMAL = 1, + SW_SHOWMINIMIZED = 2, + SW_SHOWMAXIMIZED = 3, + SW_MAXIMIZE = 3, + SW_SHOWNOACTIVATE = 4, + SW_SHOW = 5, + SW_MINIMIZE = 6, + SW_SHOWMINNOACTIVE = 7, + SW_SHOWNA = 8, + SW_RESTORE = 9, + SW_SHOWDEFAULT = 10, + SW_FORCEMINIMIZE = 11, + SW_MAX = 11 + } + + public enum WindowLong : int + { + GWL_EXSTYLE = -20, + GWL_STYLE = -16, + GWL_WNDPROC = -4, + GWL_HINSTANCE = -6, + GWL_ID = -12, + GWL_USERDATA = -21, + DWL_DLGPROC = 4, + DWL_MSGRESULT = 0, + DWL_USER = 8 + } + + public enum WindowStyles : uint + { + WS_MAXIMIZE = 0x01000000, + WS_VISIBLE = 0x10000000, + WS_POPUP = 0x80000000, + WS_BORDER = 0x00800000, + WS_CAPTION = 0x00C00000, + WS_CHILD = 0x40000000, + WS_CHILDWINDOW = 0x40000000, + WS_CLIPCHILDREN = 0x02000000, + WS_CLIPSIBLINGS = 0x04000000, + WS_DISABLED = 0x08000000, + WS_DLGFRAME = 0x00400000, + WS_GROUP = 0x00020000 + } + + public enum WindowMessage : int + { + WM_NULL = 0x0000, + WM_CREATE = 0x0001, + WM_DESTROY = 0x0002, + WM_MOVE = 0x0003, + WM_SIZE = 0x0005, + WM_ACTIVATE = 0x0006, + WM_SETFOCUS = 0x0007, + WM_KILLFOCUS = 0x0008, + WM_ENABLE = 0x000A, + WM_SETREDRAW = 0x000B, + WM_SETTEXT = 0x000C, + WM_GETTEXT = 0x000D, + WM_GETTEXTLENGTH = 0x000E, + WM_PAINT = 0x000F, + WM_CLOSE = 0x0010, + WM_QUERYENDSESSION = 0x0011, + WM_QUIT = 0x0012, + WM_QUERYOPEN = 0x0013, + WM_ERASEBKGND = 0x0014, + WM_SYSCOLORCHANGE = 0x0015, + WM_ENDSESSION = 0x0016, + WM_SHOWWINDOW = 0x0018, + WM_CTLCOLOR = 0x0019, + WM_WININICHANGE = 0x001A, + WM_SETTINGCHANGE = 0x001A, + WM_DEVMODECHANGE = 0x001B, + WM_ACTIVATEAPP = 0x001C, + WM_FONTCHANGE = 0x001D, + WM_TIMECHANGE = 0x001E, + WM_CANCELMODE = 0x001F, + WM_SETCURSOR = 0x0020, + WM_MOUSEACTIVATE = 0x0021, + WM_CHILDACTIVATE = 0x0022, + WM_QUEUESYNC = 0x0023, + WM_GETMINMAXINFO = 0x0024, + WM_PAINTICON = 0x0026, + WM_ICONERASEBKGND = 0x0027, + WM_NEXTDLGCTL = 0x0028, + WM_SPOOLERSTATUS = 0x002A, + WM_DRAWITEM = 0x002B, + WM_MEASUREITEM = 0x002C, + WM_DELETEITEM = 0x002D, + WM_VKEYTOITEM = 0x002E, + WM_CHARTOITEM = 0x002F, + WM_SETFONT = 0x0030, + WM_GETFONT = 0x0031, + WM_SETHOTKEY = 0x0032, + WM_GETHOTKEY = 0x0033, + WM_QUERYDRAGICON = 0x0037, + WM_COMPAREITEM = 0x0039, + WM_GETOBJECT = 0x003D, + WM_COMPACTING = 0x0041, + WM_COMMNOTIFY = 0x0044, + WM_WINDOWPOSCHANGING = 0x0046, + WM_WINDOWPOSCHANGED = 0x0047, + WM_POWER = 0x0048, + WM_COPYDATA = 0x004A, + WM_CANCELJOURNAL = 0x004B, + WM_NOTIFY = 0x004E, + WM_INPUTLANGCHANGEREQUEST = 0x0050, + WM_INPUTLANGCHANGE = 0x0051, + WM_TCARD = 0x0052, + WM_HELP = 0x0053, + WM_USERCHANGED = 0x0054, + WM_NOTIFYFORMAT = 0x0055, + WM_CONTEXTMENU = 0x007B, + WM_STYLECHANGING = 0x007C, + WM_STYLECHANGED = 0x007D, + WM_DISPLAYCHANGE = 0x007E, + WM_GETICON = 0x007F, + WM_SETICON = 0x0080, + WM_NCCREATE = 0x0081, + WM_NCDESTROY = 0x0082, + WM_NCCALCSIZE = 0x0083, + WM_NCHITTEST = 0x0084, + WM_NCPAINT = 0x0085, + WM_NCACTIVATE = 0x0086, + WM_GETDLGCODE = 0x0087, + WM_SYNCPAINT = 0x0088, + WM_NCMOUSEMOVE = 0x00A0, + WM_NCLBUTTONDOWN = 0x00A1, + WM_NCLBUTTONUP = 0x00A2, + WM_NCLBUTTONDBLCLK = 0x00A3, + WM_NCRBUTTONDOWN = 0x00A4, + WM_NCRBUTTONUP = 0x00A5, + WM_NCRBUTTONDBLCLK = 0x00A6, + WM_NCMBUTTONDOWN = 0x00A7, + WM_NCMBUTTONUP = 0x00A8, + WM_NCMBUTTONDBLCLK = 0x00A9, + WM_KEYDOWN = 0x0100, + WM_KEYUP = 0x0101, + WM_CHAR = 0x0102, + WM_DEADCHAR = 0x0103, + WM_SYSKEYDOWN = 0x0104, + WM_SYSKEYUP = 0x0105, + WM_SYSCHAR = 0x0106, + WM_SYSDEADCHAR = 0x0107, + WM_KEYLAST = 0x0108, + WM_IME_STARTCOMPOSITION = 0x010D, + WM_IME_ENDCOMPOSITION = 0x010E, + WM_IME_COMPOSITION = 0x010F, + WM_IME_KEYLAST = 0x010F, + WM_INITDIALOG = 0x0110, + WM_COMMAND = 0x0111, + WM_SYSCOMMAND = 0x0112, + WM_TIMER = 0x0113, + WM_HSCROLL = 0x0114, + WM_VSCROLL = 0x0115, + WM_INITMENU = 0x0116, + WM_INITMENUPOPUP = 0x0117, + WM_MENUSELECT = 0x011F, + WM_MENUCHAR = 0x0120, + WM_ENTERIDLE = 0x0121, + WM_MENURBUTTONUP = 0x0122, + WM_MENUDRAG = 0x0123, + WM_MENUGETOBJECT = 0x0124, + WM_UNINITMENUPOPUP = 0x0125, + WM_MENUCOMMAND = 0x0126, + WM_CTLCOLORMSGBOX = 0x0132, + WM_CTLCOLOREDIT = 0x0133, + WM_CTLCOLORLISTBOX = 0x0134, + WM_CTLCOLORBTN = 0x0135, + WM_CTLCOLORDLG = 0x0136, + WM_CTLCOLORSCROLLBAR = 0x0137, + WM_CTLCOLORSTATIC = 0x0138, + WM_MOUSEMOVE = 0x0200, + WM_LBUTTONDOWN = 0x0201, + WM_LBUTTONUP = 0x0202, + WM_LBUTTONDBLCLK = 0x0203, + WM_RBUTTONDOWN = 0x0204, + WM_RBUTTONUP = 0x0205, + WM_RBUTTONDBLCLK = 0x0206, + WM_MBUTTONDOWN = 0x0207, + WM_MBUTTONUP = 0x0208, + WM_MBUTTONDBLCLK = 0x0209, + WM_MOUSEWHEEL = 0x020A, + WM_PARENTNOTIFY = 0x0210, + WM_ENTERMENULOOP = 0x0211, + WM_EXITMENULOOP = 0x0212, + WM_NEXTMENU = 0x0213, + WM_SIZING = 0x0214, + WM_CAPTURECHANGED = 0x0215, + WM_MOVING = 0x0216, + WM_DEVICECHANGE = 0x0219, + WM_MDICREATE = 0x0220, + WM_MDIDESTROY = 0x0221, + WM_MDIACTIVATE = 0x0222, + WM_MDIRESTORE = 0x0223, + WM_MDINEXT = 0x0224, + WM_MDIMAXIMIZE = 0x0225, + WM_MDITILE = 0x0226, + WM_MDICASCADE = 0x0227, + WM_MDIICONARRANGE = 0x0228, + WM_MDIGETACTIVE = 0x0229, + WM_MDISETMENU = 0x0230, + WM_ENTERSIZEMOVE = 0x0231, + WM_EXITSIZEMOVE = 0x0232, + WM_DROPFILES = 0x0233, + WM_MDIREFRESHMENU = 0x0234, + WM_IME_SETCONTEXT = 0x0281, + WM_IME_NOTIFY = 0x0282, + WM_IME_CONTROL = 0x0283, + WM_IME_COMPOSITIONFULL = 0x0284, + WM_IME_SELECT = 0x0285, + WM_IME_CHAR = 0x0286, + WM_IME_REQUEST = 0x0288, + WM_IME_KEYDOWN = 0x0290, + WM_IME_KEYUP = 0x0291, + WM_MOUSEHOVER = 0x02A1, + WM_MOUSELEAVE = 0x02A3, + WM_CUT = 0x0300, + WM_COPY = 0x0301, + WM_PASTE = 0x0302, + WM_CLEAR = 0x0303, + WM_UNDO = 0x0304, + WM_RENDERFORMAT = 0x0305, + WM_RENDERALLFORMATS = 0x0306, + WM_DESTROYCLIPBOARD = 0x0307, + WM_DRAWCLIPBOARD = 0x0308, + WM_PAINTCLIPBOARD = 0x0309, + WM_VSCROLLCLIPBOARD = 0x030A, + WM_SIZECLIPBOARD = 0x030B, + WM_ASKCBFORMATNAME = 0x030C, + WM_CHANGECBCHAIN = 0x030D, + WM_HSCROLLCLIPBOARD = 0x030E, + WM_QUERYNEWPALETTE = 0x030F, + WM_PALETTEISCHANGING = 0x0310, + WM_PALETTECHANGED = 0x0311, + WM_HOTKEY = 0x0312, + WM_PRINT = 0x0317, + WM_PRINTCLIENT = 0x0318, + WM_HANDHELDFIRST = 0x0358, + WM_HANDHELDLAST = 0x035F, + WM_AFXFIRST = 0x0360, + WM_AFXLAST = 0x037F, + WM_PENWINFIRST = 0x0380, + WM_PENWINLAST = 0x038F, + WM_APP = 0x8000, + WM_USER = 0x0400, + WM_REFLECT = WM_USER + 0x1c00, + WM_CHANGEUISTATE = 0x0127, + WM_UPDATEUISTATE = 0x0128, + WM_QUERYUISTATE = 0x0129 + } + + public enum WindowUIState : int + { + UIS_SET = 1, + UIS_CLEAR = 2, + UIS_INITIALIZE = 3 + } + + public enum CSIDL : int + { + CSIDL_DESKTOP = 0x0000, // + CSIDL_INTERNET = 0x0001, // Internet Explorer (icon on desktop) + CSIDL_PROGRAMS = 0x0002, // Start Menu\Programs + CSIDL_CONTROLS = 0x0003, // My Computer\Control Panel + CSIDL_PRINTERS = 0x0004, // My Computer\Printers + CSIDL_PERSONAL = 0x0005, // My Documents + CSIDL_FAVORITES = 0x0006, // \Favorites + CSIDL_STARTUP = 0x0007, // Start Menu\Programs\Startup + CSIDL_RECENT = 0x0008, // \Recent + CSIDL_SENDTO = 0x0009, // \SendTo + CSIDL_BITBUCKET = 0x000a, // \Recycle Bin + CSIDL_STARTMENU = 0x000b, // \Start Menu + CSIDL_MYDOCUMENTS = 0x000c, // logical "My Documents" desktop icon + CSIDL_MYMUSIC = 0x000d, // "My Music" folder + CSIDL_MYVIDEO = 0x000e, // "My Videos" folder + CSIDL_DESKTOPDIRECTORY = 0x0010, // \Desktop + CSIDL_DRIVES = 0x0011, // My Computer + CSIDL_NETWORK = 0x0012, // Network Neighborhood (My Network Places) + CSIDL_NETHOOD = 0x0013, // \nethood + CSIDL_FONTS = 0x0014, // windows\fonts + CSIDL_TEMPLATES = 0x0015, + CSIDL_COMMON_STARTMENU = 0x0016, // All Users\Start Menu + CSIDL_COMMON_PROGRAMS = 0X0017, // All Users\Start Menu\Programs + CSIDL_COMMON_STARTUP = 0x0018, // All Users\Startup + CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019, // All Users\Desktop + CSIDL_APPDATA = 0x001a, // \Application Data + CSIDL_PRINTHOOD = 0x001b, // \PrintHood + CSIDL_LOCAL_APPDATA = 0x001c, // \Local Settings\Applicaiton Data (non roaming) + CSIDL_ALTSTARTUP = 0x001d, // non localized startup + CSIDL_COMMON_ALTSTARTUP = 0x001e, // non localized common startup + CSIDL_COMMON_FAVORITES = 0x001f, + CSIDL_INTERNET_CACHE = 0x0020, + CSIDL_COOKIES = 0x0021, + CSIDL_HISTORY = 0x0022, + CSIDL_COMMON_APPDATA = 0x0023, // All Users\Application Data + CSIDL_WINDOWS = 0x0024, // GetWindowsDirectory() + CSIDL_SYSTEM = 0x0025, // GetSystemDirectory() + CSIDL_PROGRAM_FILES = 0x0026, // C:\Program Files + CSIDL_MYPICTURES = 0x0027, // C:\Program Files\My Pictures + CSIDL_PROFILE = 0x0028, // USERPROFILE + CSIDL_SYSTEMX86 = 0x0029, // x86 system directory on RISC + CSIDL_PROGRAM_FILESX86 = 0x002a, // x86 C:\Program Files on RISC + CSIDL_PROGRAM_FILES_COMMON = 0x002b, // C:\Program Files\Common + CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c, // x86 Program Files\Common on RISC + CSIDL_COMMON_TEMPLATES = 0x002d, // All Users\Templates + CSIDL_COMMON_DOCUMENTS = 0x002e, // All Users\Documents + CSIDL_COMMON_ADMINTOOLS = 0x002f, // All Users\Start Menu\Programs\Administrative Tools + CSIDL_ADMINTOOLS = 0x0030, // \Start Menu\Programs\Administrative Tools + CSIDL_CONNECTIONS = 0x0031, // Network and Dial-up Connections + CSIDL_COMMON_MUSIC = 0x0035, // All Users\My Music + CSIDL_COMMON_PICTURES = 0x0036, // All Users\My Pictures + CSIDL_COMMON_VIDEO = 0x0037, // All Users\My Video + CSIDL_CDBURN_AREA = 0x003b // USERPROFILE\Local + } + + public enum SHGFP_TYPE : int + { + SHGFP_TYPE_CURRENT = 0, + SHGFP_TYPE_DEFAULT = 1 + } + + public enum DesiredAccess : int + { + DELETE = 0x00010000, // Required to delete the object. + READ_CONTROL = 0x00020000, // Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right. + SYNCHRONIZE = 0x00100000, // The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state. + WRITE_DAC = 0x00040000, // Required to modify the DACL in the security descriptor for the object. + WRITE_OWNER = 0x00080000 // Required to change the owner in the security descriptor for the object. + } + + public enum WaitTime : uint + { + IGNORE = 0, // Ignore signal + INFINITE = 0xFFFFFFFF // Infinite timeout + } + + public enum SystemMetric : int + { + SM_CXSCREEN = 0, + SM_CYSCREEN = 1, + SM_CXVSCROLL = 2, + SM_CYHSCROLL = 3, + SM_CYCAPTION = 4, + SM_CXBORDER = 5, + SM_CYBORDER = 6, + SM_CXDLGFRAME = 7, + SM_CYDLGFRAME = 8, + SM_CYVTHUMB = 9, + SM_CXHTHUMB = 10, + SM_CXICON = 11, + SM_CYICON = 12, + SM_CXCURSOR = 13, + SM_CYCURSOR = 14, + SM_CYMENU = 15, + SM_CXFULLSCREEN = 16, + SM_CYFULLSCREEN = 17, + SM_CYKANJIWINDOW = 18, + SM_MOUSEPRESENT = 19, + SM_CYVSCROLL = 20, + SM_CXHSCROLL = 21, + SM_DEBUG = 22, + SM_SWAPBUTTON = 23, + SM_RESERVED1 = 24, + SM_RESERVED2 = 25, + SM_RESERVED3 = 26, + SM_RESERVED4 = 27, + SM_CXMIN = 28, + SM_CYMIN = 29, + SM_CXSIZE = 30, + SM_CYSIZE = 31, + SM_CXFRAME = 32, + SM_CYFRAME = 33, + SM_CXMINTRACK = 34, + SM_CYMINTRACK = 35, + SM_CXDOUBLECLK = 36, + SM_CYDOUBLECLK = 37, + SM_CXICONSPACING = 38, + SM_CYICONSPACING = 39, + SM_MENUDROPALIGNMENT = 40, + SM_PENWINDOWS = 41, + SM_DBCSENABLED = 42, + SM_CMOUSEBUTTONS = 43 + } + + public enum SetWindowPosFlags : uint + { + SWP_NOSIZE = 0x0001, + SWP_NOMOVE = 0x0002, + SWP_NOZORDER = 0x0004, + SWP_NOREDRAW = 0x0008, + SWP_NOACTIVATE = 0x0010, + SWP_FRAMECHANGED = 0x0020, + SWP_SHOWWINDOW = 0x0040, + SWP_HIDEWINDOW = 0x0080, + SWP_NOCOPYBITS = 0x0100, + SWP_NOOWNERZORDER = 0x0200, + SWP_NOSENDCHANGING = 0x0400, + SWP_DRAWFRAME = SWP_FRAMECHANGED, + SWP_NOREPOSITION = SWP_NOOWNERZORDER + } + + public enum WindowLayerAttributes + { + LWA_COLORKEY = 0x00000001, + LWA_ALPHA = 0x00000002 + } + + public enum WindowPos : int + { + HWND_TOP = 0, + HWND_BOTTOM = 1, + HWND_TOPMOST = -1, + HWND_NOTOPMOST = -2 + } + + public enum VK : ushort + { + SHIFT = 0x10, + CONTROL = 0x11, + MENU = 0x12, + ESCAPE = 0x1B, + BACK = 0x08, + TAB = 0x09, + RETURN = 0x0D, + PRIOR = 0x21, + NEXT = 0x22, + END = 0x23, + HOME = 0x24, + LEFT = 0x25, + UP = 0x26, + RIGHT = 0x27, + DOWN = 0x28, + SELECT = 0x29, + PRINT = 0x2A, + EXECUTE = 0x2B, + SNAPSHOT = 0x2C, + INSERT = 0x2D, + DELETE = 0x2E, + HELP = 0x2F, + NUMPAD0 = 0x60, + NUMPAD1 = 0x61, + NUMPAD2 = 0x62, + NUMPAD3 = 0x63, + NUMPAD4 = 0x64, + NUMPAD5 = 0x65, + NUMPAD6 = 0x66, + NUMPAD7 = 0x67, + NUMPAD8 = 0x68, + NUMPAD9 = 0x69, + MULTIPLY = 0x6A, + ADD = 0x6B, + SEPARATOR = 0x6C, + SUBTRACT = 0x6D, + DECIMAL = 0x6E, + DIVIDE = 0x6F, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7A, + F12 = 0x7B, + OEM_1 = 0xBA, // ',:' for US + OEM_PLUS = 0xBB, // '+' any country + OEM_COMMA = 0xBC, // ',' any country + OEM_MINUS = 0xBD, // '-' any country + OEM_PERIOD = 0xBE, // '.' any country + OEM_2 = 0xBF, // '/?' for US + OEM_3 = 0xC0, // '`~' for US + MEDIA_NEXT_TRACK = 0xB0, + MEDIA_PREV_TRACK = 0xB1, + MEDIA_STOP = 0xB2, + MEDIA_PLAY_PAUSE = 0xB3, + LWIN = 0x5B, + RWIN = 0x5C + } + + public enum AssocF : ushort + { + Init_NoRemapCLSID = 0x1, + Init_ByExeName = 0x2, + Open_ByExeName = 0x2, + Init_DefaultToStar = 0x4, + Init_DefaultToFolder = 0x8, + NoUserSettings = 0x10, + NoTruncate = 0x20, + Verify = 0x40, + RemapRunDll = 0x80, + NoFixUps = 0x100, + IgnoreBaseClass = 0x200 + } + + public enum AssocStr : ushort + { + Command = 1, + Executable, + FriendlyDocName, + FriendlyAppName, + NoOpen, + ShellNewValue, + DDECommand, + DDEIfExec, + DDEApplication, + DDETopic + } + + #endregion + + //// + // Win32 Structures + //// + #region Win32 Structures + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + + public Rectangle AsRectangle + { + get + { + return new Rectangle(this.left, this.top, this.right - this.left, this.bottom - this.top); + } + } + + public static RECT FromXYWH(int x, int y, int width, int height) + { + RECT rect = new RECT(); + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + return rect; + } + + public static RECT FromRectangle(Rectangle rectangle) + { + RECT rect = new RECT(); + rect.left = rectangle.Left; + rect.top = rectangle.Top; + rect.right = rectangle.Right; + rect.bottom = rectangle.Bottom; + return rect; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct SIZE + { + public int cx; + public int cy; + } + + [StructLayout(LayoutKind.Sequential)] + public struct ShellExecuteInfo + { + public int cbSize; + public uint fMask; + public IntPtr hwnd; + public string lpVerb; + public string lpFile; + public string lpParameters; + public string lpDirectory; + public uint nShow; + public IntPtr hInstApp; + public IntPtr lpIDList; + public string lpClass; + public IntPtr hkeyClass; + public uint dwHotKey; + public IntPtr hIcon_Monitor; // union DUMMYUNIONNAME + public IntPtr hProcess; + } + + [StructLayout(LayoutKind.Explicit, Size = 28)] + public struct INPUT + { + [FieldOffset(0)] + public uint type; + [FieldOffset(4)] + public KEYBDINPUT ki; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct KEYBDINPUT + { + public ushort wVk; + public ushort wScan; + public uint dwFlags; + public long time; + public uint dwExtraInfo; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct MONITORINFOEX + { + public int cbSize; + public RECT rcMonitor; + public RECT rcWork; + public int dwFlags; + [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] + public string szDeviceName; + } + + #endregion + + //// + // .Net Win32 Wrapper Functions + //// + public class Win32_WrapperFunc + { + /// + /// Get a windows client rectangle in a .NET structure + /// + /// The window handle to look up + /// The rectangle + public static Rectangle GetClientRect(IntPtr hwnd) + { + RECT rect = new RECT(); + Win32Functions.GetClientRect(hwnd, out rect); + return rect.AsRectangle; + } + + /// + /// Get a windows rectangle in a .NET structure + /// + /// The window handle to look up + /// The rectangle + public static Rectangle GetWindowRect(IntPtr hwnd) + { + RECT rect = new RECT(); + Win32Functions.GetWindowRect(hwnd, out rect); + return rect.AsRectangle; + } + + /// + /// Get's the System's registered file for the corresponding File + /// + /// full file name and path + /// Returns Registered exe for file in Uppercase + public static string GetRegisteredExeForFile(string fileNameAndPath) + { + if (!String.IsNullOrEmpty(fileNameAndPath)) + { + bool bIsValidExe = false; + string strExeOrDllPath = string.Empty; + bool bSuccess = Win32_WrapperFunc.FindExeOrDll(fileNameAndPath, out strExeOrDllPath, out bIsValidExe); + + if (bSuccess && bIsValidExe) + return Path.GetFileName(strExeOrDllPath).ToUpper(); + } + return string.Empty; + } + + /// + /// Useful for finding who is responsible by Shell32 to handle this file + /// + /// full qualifying path to File + /// will contain that path that is found in the registry + /// true if the return value is a valid exe, false if it is a Dll + /// true if a match was found, false otherwise + public static bool FindExeOrDll(string fileNameAndPath, out string strExeOrDllPath, out bool IsValidExe) + { + if (!String.IsNullOrEmpty(fileNameAndPath)) + { + // Try FindExecutable first + StringBuilder retStr = new StringBuilder(); + int ret = (int)Win32Functions.FindExecutable(fileNameAndPath, null, retStr); + strExeOrDllPath = retStr.ToString(); + + // If FindExe Failed, try AssocQueryString instead + if (String.IsNullOrEmpty(strExeOrDllPath)) + { + string Ext = Path.GetExtension(fileNameAndPath); + StringBuilder retStr2 = new StringBuilder(); + uint pcchOut = Win32_Constants.MAX_PATH; + Win32Functions.AssocQueryString(0, AssocStr.Executable, Ext, "open", retStr2, ref pcchOut); + + if (retStr2.Length > 0) + strExeOrDllPath = retStr2.ToString(); + } + + IsValidExe = false; + if (!String.IsNullOrEmpty(strExeOrDllPath)) + { + string Ext = Path.GetExtension(strExeOrDllPath); + IsValidExe = (Ext.ToUpper() == ".EXE"); + return true; + } + } + strExeOrDllPath = string.Empty; + IsValidExe = false; + return false; + } + + /// + /// Uses Shell32 to get the Windows location on this computer + /// + /// path to windows dir on this machine + public static string GetWindowsPath() + { + StringBuilder windowsPath = new StringBuilder(); + Win32Functions.SHGetFolderPath(IntPtr.Zero, (int)CSIDL.CSIDL_WINDOWS, IntPtr.Zero, (int)SHGFP_TYPE.SHGFP_TYPE_CURRENT, windowsPath); + return windowsPath.ToString(); + } + + /// + /// Use this function to set transparency of a layered top level window. + /// This will only work on Windows that are part of your own Process Space. calling this on external windows, + /// outside of your process SetLayeredWindowAttributes() will fail. + /// + /// the window to make or unmake transparent + /// 0 for transparent 255 for totally visible + public static void SetAlphaChannel(IntPtr hWnd, byte alpha) + { + long dwStyle = (long) Win32Functions.GetWindowLong(hWnd, (int) ((int) WindowLong.GWL_EXSTYLE | (int) Win32_Constants.WS_EX_LAYERED)); + long retVal = Win32Functions.SetWindowLong(hWnd, (int) WindowLong.GWL_EXSTYLE, (int) dwStyle); + + if (retVal == 0) + Trace.Write("SetAlphaChannel's SetWindowLong Failed"); + + bool bSuccess = Win32Functions.SetLayeredWindowAttributes(hWnd, (int)Win32Functions.RGB(0, 0, 0), alpha, (uint)(WindowLayerAttributes.LWA_ALPHA)); + if (!bSuccess) + Trace.Write("SetAlphaChannel's SetLayeredWindowAttributes Failed"); + } + + /// + /// Could be useful later - maybe + /// + /// + //public static Rectangle GetAbsoluteClientRect(IntPtr hWnd) + //{ + // //Rectangle windowRect = Win32Functions.GetWindowRect(hWnd); + // //Rectangle clientRect = Win32Functions.GetClientRect(hWnd); + + // //// This gives us the width of the left, right and bottom chrome - we can then determine the top height + // //int chromeWidth = (int)((windowRect.Width - clientRect.Width) / 2); + // //return new Rectangle(new Point(windowRect.X + chromeWidth, windowRect.Y + (windowRect.Height - clientRect.Height - chromeWidth)), clientRect.Size); + //} + + } + + //// + // Win32 Constants + //// + public class Win32_Constants + { + public const ushort KEYEVENTF_KEYUP = 0x0002; + public const int SRCCOPY = 0x00CC0020; + public const int CAPTUREBLT = 0x40000000; + public const int MONITOR_DEFAULTTONEAREST = 0x00000002; + public const int WM_USER = 0x0400; + public const int WS_EX_LAYERED = 0x00080000; + public const int MAX_PATH = 260; + } + + //// + // Win32 Functions + //// + public class Win32Functions + { + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + + public static int LOWORD(int n) + { + return (n & 0xffff); + } + public static int HIWORD(int n) + { + return ((n >> 16) & 0xffff); + } + public static int RGB(int r, int g, int b) + { + int rs = r & 0xffff; + int gs = (g << 8) & 0xffff; + int bs = (b << 16) & 0xffff; + return (rs | gs | bs); + } + + //// + // Shell32 + //// + #region Shell32 + + [DllImport("shell32.dll")] + public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); + + [DllImport("shell32.dll", SetLastError = true)] + extern public static bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo); + + [DllImport("shell32.dll")] + extern public static IntPtr FindExecutable(string lfFile, string lpDirectory, [Out] StringBuilder lpResult); + + [DllImport("shell32.dll")] + extern public static long SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, [Out] StringBuilder pszPath); + + #endregion + + //// + // User32 + //// + #region User32 + + [DllImport("user32.dll")] + public static extern IntPtr SetFocus(IntPtr hwnd); + + [DllImport("user32.dll")] + public static extern IntPtr GetFocus(); + + [DllImport("user32.dll")] + public static extern IntPtr SetActiveWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + extern public static IntPtr SetParent(IntPtr child, IntPtr newParent); + + [DllImport("user32.dll")] + extern public static long SetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong); + + [DllImport("user32.dll")] + extern public static long GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("User32.dll")] + extern public static int SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + extern public static bool SetLayeredWindowAttributes(IntPtr hwnd, Int32 crKey, byte bAlpha, uint dwFlags); + + [DllImport("User32.dll")] + extern public static IntPtr GetForegroundWindow(); + + [DllImport("User32.dll")] + extern public static bool IsWindow(IntPtr hwnd); + + [DllImport("user32.dll")] + extern public static int ShowWindow(IntPtr hwnd, int nCmdShow); + + [DllImport("user32.dll")] + extern public static int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + + [DllImport("user32.dll")] + extern public static bool GetWindowRect(IntPtr hWnd, out RECT rect); + + [DllImport("user32.dll")] + extern public static bool GetClientRect(IntPtr hWnd, out RECT rect); + + [DllImport("User32.dll")] + extern public static bool EnumWindows(Delegate lpEnumFunc, IntPtr lParam); + + [DllImport("User32.dll")] + extern public static int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId); + + [DllImport("User32.dll")] + extern public static bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll")] + public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); + + [DllImport("User32.dll")] + extern public static int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll")] + extern public static int GetSystemMetrics(int index); + + [DllImport("user32.dll")] + extern public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); + + [DllImport("user32.dll")] + public static extern IntPtr GetDesktopWindow(); + + [DllImport("user32.dll")] + public static extern IntPtr GetDC(IntPtr ptr); + + [DllImport("user32.dll")] + public static extern IntPtr GetWindowDC(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, int flags); + + [DllImport("user32.dll")] + public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc); + + [DllImport("user32.dll")] + public static extern bool EmptyClipboard(); + + [DllImport("user32.dll")] + public static extern int GetClipboardSequenceNumber(); + + [DllImport("user32.dll")] + public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX monitorinfo); + + [DllImport("user32.dll")] + public static extern IntPtr MonitorFromRect(ref RECT rect, int dwFlags); + + #endregion + + //// + // Kernel32 + //// + #region Kernel32 + + [DllImport("kernel32.dll")] + internal static extern IntPtr LoadLibrary(String dllname); + + [DllImport("kernel32.dll")] + internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname); + + [DllImport("kernel32.dll")] + extern public static int GetProcessId(IntPtr hProcess); + + [DllImport("kernel32.dll")] + extern public static IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll")] + extern public static int WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + [DllImport("kernel32.dll")] + extern public static int GetLastError(); + + [DllImport("kernel32.dll")] + // lpEventAttributes should be a ref to a SECURITY_ATTRIBUTES struct, but we only pass in NULL so we can just make it an IntPtr + extern public static IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, [In] StringBuilder lpName); + + [DllImport("kernel32.dll")] + extern public static IntPtr SetEvent(IntPtr hEvent); + + [DllImport("kernel32.dll")] + extern public static bool CloseHandle(IntPtr hHandle); + + [DllImport("kernel32.dll")] + extern public static int GlobalAddAtom([In] StringBuilder lpString); + + [DllImport("kernel32.dll")] + extern public static int GlobalDeleteAtom(int nAtom); + + #endregion + + //// + // Shlwapi + //// + [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, [In][Out] ref uint pcchOut); + + //// + // Ole32 + //// + [DllImport("ole32.dll")] + public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); + + //// + // Uxtheme + //// + [DllImport("uxTheme.dll")] + extern public static bool IsAppThemed(); + + //// + // Dwmapi + //// + [DllImport("dwmapi.dll")] + extern public static long DwmIsCompositionEnabled(ref bool pfEnabled); + + //// + // GDI32 + //// + #region GDI32 + + [DllImport("gdi32.dll")] + public static extern IntPtr DeleteDC(IntPtr hDc); + + [DllImport("gdi32.dll")] + public static extern IntPtr DeleteObject(IntPtr hDc); + + [DllImport("gdi32.dll")] + public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp); + + [DllImport("gdi32.dll")] + public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); + + [DllImport("gdi32.dll")] + public static extern IntPtr CreateCompatibleDC(IntPtr hdc); + + [DllImport("gdi32.dll")] + public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp); + + [DllImport("gdi32.dll")] + public static extern IntPtr CreateDC(string lpszDriver, IntPtr passNULL, IntPtr passNULL2, IntPtr passNULL3); + + #endregion + + //// + // Helper .Net Functions + //// + // .net implementation of EnumWindowsProc Callback + public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + public interface IWindowHandleAccess + { + IntPtr hWnd + { + get; + set; + } + } + + public static IntPtr GetWindowHandle(EnumWindowsProc proc, Context context) where Context : IWindowHandleAccess + { + // Initialize unmanged memory to hold the struct. + IntPtr pContext = Marshal.AllocHGlobal(Marshal.SizeOf(context)); + + try + { + // Copy the struct to unmanaged memory. + Marshal.StructureToPtr(context, pContext, false); + + bool bFound = false; + int numTries = 5; + + while (!bFound && numTries != 0) + { + Win32Functions.EnumWindows(proc, pContext); + + // Marshall context back to managed + context = (Context)Marshal.PtrToStructure(pContext, typeof(Context)); + + if (context.hWnd != IntPtr.Zero) + { + bFound = true; + } + else + { + // Sleep a little and try again + Thread.Sleep(500); + --numTries; + } + } + } + finally + { + Log.ErrorFormat("{0}() - Unknown exception occured!", MethodBase.GetCurrentMethod().Name); + + // Free the unmanaged memory. + Marshal.FreeHGlobal(pContext); + } + + return context.hWnd; + } + + [StructLayout(LayoutKind.Sequential)] + public struct EnumWindowsContext_pid_filename : IWindowHandleAccess + { + public int targetPid; + public string filePath; + private IntPtr _hWnd; + + public IntPtr hWnd + { + get + { + return _hWnd; + } + + set + { + _hWnd = value; + } + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct EnumWindowsContext_filePath : IWindowHandleAccess + { + public string filePath; + private IntPtr _hWnd; + + public IntPtr hWnd + { + get + { + return _hWnd; + } + + set + { + _hWnd = value; + } + } + } + + public static bool EnumWindowProcImpl_filePath(IntPtr hWnd, IntPtr pContext) + { + bool bContinueEnumerating = true; + + // Marshall context back to managed + EnumWindowsContext_filePath context = new EnumWindowsContext_filePath(); + context = (EnumWindowsContext_filePath)Marshal.PtrToStructure(pContext, typeof(EnumWindowsContext_filePath)); + + // Check if filePath is the text in the window title bar + if (IsTitleBar(hWnd, context.filePath)) + { + Log.InfoFormat("{0}() - found!", MethodBase.GetCurrentMethod().Name); + context.hWnd = hWnd; + + // Marshall changed data back to unmanaged + Marshal.StructureToPtr(context, pContext, false); + bContinueEnumerating = false; + } + + return bContinueEnumerating; + } + + public static bool EnumWindowProcImpl_pid_filename(IntPtr hWnd, IntPtr pContext) + { + bool bContinueEnumerating = true; + + int currentPid = 0; + GetWindowThreadProcessId(hWnd, ref currentPid); + + // Marshall context back to managed + EnumWindowsContext_pid_filename context = new EnumWindowsContext_pid_filename(); + context = (EnumWindowsContext_pid_filename)Marshal.PtrToStructure(pContext, typeof(EnumWindowsContext_pid_filename)); + + if (currentPid == context.targetPid) + { + Log.InfoFormat("{0}() - currentpid = {1} vs. targetPid = {2} hwnd = {3}", MethodBase.GetCurrentMethod().Name, currentPid, context.targetPid, hWnd.ToString("X")); + + // Check if fileName is in window title bar + if (IsFilenameInTitleBar(hWnd, context.filePath)) + { + Log.InfoFormat("{0}() - found!", MethodBase.GetCurrentMethod().Name); + context.hWnd = hWnd; + + // Marshall changed data back to unmanaged + Marshal.StructureToPtr(context, pContext, false); + bContinueEnumerating = false; + } + } + + return bContinueEnumerating; + } + + public static bool IsFilenameInTitleBar(IntPtr hWnd, string filePath) + { + bool bFound = false; + int maxTextSize = 256; + + StringBuilder titleBarText = new StringBuilder(maxTextSize); + + if (GetWindowText(hWnd, titleBarText, maxTextSize) > 0) + { + string fileName = Path.GetFileName(filePath); + + if (fileName.Length > 0) + { + if (titleBarText.ToString().ToLower().IndexOf(fileName.ToLower()) != -1) + { + bFound = true; + } + } + } + + return bFound; + } + + public static bool IsTitleBar(IntPtr hWnd, string filePath) + { + bool bFound = false; + int maxTextSize = 256; + + StringBuilder titleBarText = new StringBuilder(maxTextSize); + + if (GetWindowText(hWnd, titleBarText, maxTextSize) > 0) + { + if (filePath.Length > 0) + { + if (titleBarText.ToString().ToLower().CompareTo(filePath.ToLower()) == 0) + { + bFound = true; + } + } + } + + return bFound; + } + + public static string GetProcessName(IntPtr hWnd) + { + int currentPid = 0; + Win32Functions.GetWindowThreadProcessId(hWnd, ref currentPid); + + Process process; + try + { + process = Process.GetProcessById(currentPid); + } + catch (ArgumentException e) + { + // This is thrown when Process.GetProcessById cannot find the process + throw e; + } + + return process.ProcessName; + } + + /// + /// Returns the .Net Process Object that owns the passed in hWnd + /// + /// handle to a Window + /// a .Net Process or throws an error + public static Process GetProcessFromHandle(IntPtr hWnd) + { + try + { + int currentPid = 0; + Win32Functions.GetWindowThreadProcessId(hWnd, ref currentPid); + + Process process; + process = Process.GetProcessById(currentPid); + return process; + } + catch (ArgumentException e) + { + // This is thrown when Process.GetProcessById cannot find the process + throw e; + } + } + + /// + /// Attaches to instance of COM object matching progid + /// and returns an object. Client must cast and know + /// expected type. + /// + public static Object GetCOMObject(string progId) + { + Object app = null; + try + { + app = Marshal.GetActiveObject(progId); + } + catch (SystemException e) + { + string d = e.ToString(); + } + + return app; + } + + public struct RunningObject + { + public string name; + public object o; + } + + /// + /// Use this to Get All Running Objects in the ROT + /// + public static List GetRunningObjects() + { + // Get the table. + var res = new List(); + IBindCtx bc; + + CreateBindCtx(0, out bc); + IRunningObjectTable runningObjectTable; + + bc.GetRunningObjectTable(out runningObjectTable); + IEnumMoniker monikerEnumerator; + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + // Enumerate and fill our nice dictionary. + IMoniker[] monikers = new IMoniker[1]; + IntPtr numFetched = IntPtr.Zero; + + while (monikerEnumerator.Next(1, monikers, numFetched) == 0) + { + RunningObject running; + monikers[0].GetDisplayName(bc, null, out running.name); + runningObjectTable.GetObject(monikers[0], out running.o); + res.Add(running); + } + return res; + } + + /// + /// Use this to Get A specific type of Object from the ROT + /// + public static List GetRunningObjectsOfType() + { + // Get the table. + var res = new List(); + IBindCtx bc; + + CreateBindCtx(0, out bc); + IRunningObjectTable runningObjectTable; + + bc.GetRunningObjectTable(out runningObjectTable); + IEnumMoniker monikerEnumerator; + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + // Enumerate and fill our nice dictionary. + IMoniker[] monikers = new IMoniker[1]; + IntPtr numFetched = IntPtr.Zero; + + while (monikerEnumerator.Next(1, monikers, numFetched) == 0) + { + object o; + runningObjectTable.GetObject(monikers[0], out o); + + if (o is T) + { + res.Add((T) o); + } + o = null; + } + return res; + } + + } +} diff --git a/Platform/app.config b/Platform/app.config new file mode 100644 index 0000000..b7db281 --- /dev/null +++ b/Platform/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Satellite/GUI.Designer.cs b/Satellite/GUI.Designer.cs new file mode 100644 index 0000000..290695e --- /dev/null +++ b/Satellite/GUI.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Satellite { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class GUI { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal GUI() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.Satellite.GUI", typeof(GUI).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Hello, My Name is Doris - JAJAJA. + /// + internal static string TEST_STRING { + get { + return ResourceManager.GetString("TEST_STRING", resourceCulture); + } + } + } +} diff --git a/Satellite/GUI.de.resx b/Satellite/GUI.de.resx new file mode 100644 index 0000000..85c9090 --- /dev/null +++ b/Satellite/GUI.de.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Satellite/GUI.en.resx b/Satellite/GUI.en.resx new file mode 100644 index 0000000..5117373 --- /dev/null +++ b/Satellite/GUI.en.resx @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Artifact Wall + Group Header in 'Settings' for Artifact Wall + + + Workspace Selector + Group Header in 'Settings' for Workspace Selector + + + About Us + Tab Header for 'About Us' Tab + + + Help + Tab Header for 'Help' Tab + + + Settings + Tab Header for 'Settings' Tab + + \ No newline at end of file diff --git a/Satellite/GUI.resx b/Satellite/GUI.resx new file mode 100644 index 0000000..0e0012c --- /dev/null +++ b/Satellite/GUI.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Hello, My Name is Doris - JAJAJA + What is going on? + + \ No newline at end of file diff --git a/Satellite/MyKeyFile.SNK b/Satellite/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Satellite/MyKeyFile.SNK differ diff --git a/Satellite/Properties/AssemblyInfo.cs b/Satellite/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a6fb99a --- /dev/null +++ b/Satellite/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Satellite")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Satellite")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b241af6c-dd72-4c16-b1e1-b009c61e7641")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Satellite/Satellite.csproj b/Satellite/Satellite.csproj new file mode 100644 index 0000000..0e396c8 --- /dev/null +++ b/Satellite/Satellite.csproj @@ -0,0 +1,69 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {6DC93F91-D6D4-4C35-8A83-C180E8E22E16} + Library + Properties + Foo.Satellite + Satellite + v3.5 + 512 + true + MyKeyFile.SNK + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + + + True + True + GUI.resx + + + + + + + + ResXFileCodeGenerator + GUI.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/Settings/AppConfig.xml b/Settings/AppConfig.xml new file mode 100644 index 0000000..80a6979 --- /dev/null +++ b/Settings/AppConfig.xml @@ -0,0 +1,29 @@ + + + + + IEXPLORE.EXE + WINWORD.EXE + EXCEL.EXE + POWERPNT.EXE + MSPUB.EXE + VISIO.EXE + MSACCESS.EXE + ACROBAT.EXE + NOTEPAD.EXE + PAINT.EXE + WORDPAD.EXE + HH.EXE + + + + + + + + + 3 + + + + \ No newline at end of file diff --git a/Settings/ButtonThemeSetting.cs b/Settings/ButtonThemeSetting.cs new file mode 100644 index 0000000..3619852 --- /dev/null +++ b/Settings/ButtonThemeSetting.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Runtime.InteropServices; + +namespace Foo.Settings +{ + + /// + /// Use this to specificy the names of each themed button + /// + [ComVisible(false)] + public static class ButtonNames + { + public const string BUTTON_UP = "ButtonUp.ico"; + public const string BUTTON_DOWN = "ButtonDown.ico"; + public const string TOGGLE_UP = "ToggleUp.ico"; + } + /// + /// Button Location Interface for COM + /// + [Guid("CFE7FDB8-E3F0-45aa-9935-C9A8502FF7DF")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + [ComVisible(true)] + public interface IButtonIconLocation + { + string GetBUTTON_UP(); + string GetBUTTON_DOWN(); + string GetTOGGLE_UP(); + } + /// + /// Button Theme Settings COM + /// + [Guid("F82358CD-8521-4d03-AFF9-352491E9A10E")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + [ComVisible(true)] + public interface IButtonThemeSetting + { + int Top(); + int Right(); + int Height(); + int Width(); + } + /// + /// Parent Class for all the Button Shared Code - *MAIN class for everthing basically* + /// + [ComVisible(false)] + public class ButtonSharedCode : IButtonThemeSetting, IButtonIconLocation + { + private string m_RelativePath = ""; + private string m_AssemblyPath = ""; + private int m_nTop = 0; + private int m_nRight = 0; + private int m_nHeight = 0; + private int m_nWidth = 0; + + /// + /// Constructor for SharedButtonCode + /// + /// relative location (folder) inside running application directory + /// Theme specific Top location for Button + /// Theme specific Right location for Button + /// Theme specific Height of Button + /// Theme specific Width of Button + public ButtonSharedCode(string strRelativeLoc, int nTop, int nRight, int nHeight, int nWidth) + { + // Theme settings are stored in the Platform Path + //m_AssemblyPath = Platform.InstallationSpec.PlatformPath; + m_AssemblyPath = Platform.InstallationSpec.InstallPath; + + // Debug path + //m_AssemblyPath = @"C:\_ROOT_\Ooganizer\Ooganizer_1.0\Target\debug\Platform"; + + m_RelativePath = strRelativeLoc; + + m_nTop = nTop; + m_nRight = nRight; + m_nHeight = nHeight; + m_nWidth = nWidth; + } + + //// + // IButtonThemeSetting + //// + public int Top() { return m_nTop; } + public int Right() { return m_nRight; } + public int Height() { return m_nHeight; } + public int Width() { return m_nWidth; } + + //// + // IButtonLocation + //// + public string GetBUTTON_UP() { return (m_AssemblyPath + "\\" + m_RelativePath + "\\" + ButtonNames.BUTTON_UP); } + public string GetBUTTON_DOWN() { return (m_AssemblyPath + "\\" + m_RelativePath + "\\" + ButtonNames.BUTTON_DOWN); } + public string GetTOGGLE_UP() { return (m_AssemblyPath + "\\" + m_RelativePath + "\\" + ButtonNames.TOGGLE_UP); } + } + /// + /// Classic Button Theme Setting + /// + [ComVisible(false)] + public class ButtonClassicTheme : ButtonSharedCode + { + public ButtonClassicTheme() : base("Resources\\Themes\\ClassicTheme", 0, 0, 0, 0) { } + } + /// + /// XP Button Theme Setting + /// + [ComVisible(false)] + public class ButtonXPTheme : ButtonSharedCode + { + public ButtonXPTheme() : base("Resources\\Themes\\XPTheme", 1, 126, 16, 26) { } + } + /// + /// Aero Button Theme Setting + /// + [ComVisible(false)] + public class ButtonAeroTheme : ButtonSharedCode + { + //public ButtonAeroTheme() : base("Resources\\AeroTheme", 0, 129, 18, 26) { } + public ButtonAeroTheme() : base("Resources\\Themes\\AeroTheme", 1, 126, 16, 26) { } + } + /// + /// Vista No Aero Theme Setting + /// + [ComVisible(false)] + public class ButtonVistaNoAeroTheme : ButtonSharedCode + { + public ButtonVistaNoAeroTheme() : base("Resources\\Themes\\VistaNoAeroTheme", 0, 0, 15, 28) { } + } + /// + /// This class abstracts away all the settings we need for + /// ButtonHook to deal with themes and Buttons. (we may consider in the future + /// to use this class to retrieve custom settings) + /// ~this class is accessible via COM for the W32Button to work + /// + [Guid("9EEC54A0-77F3-4dcf-8C74-B6720437C59E")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ProgId("Ooganizer.ButtonThemeNIconSettingsCCW")] + [ComVisible(true)] + public class ButtonThemeNIconSettingsCCW + { + private object m_oButtonThemeObject = null; + + public ButtonThemeNIconSettingsCCW() + { + switch (Foo.Platform.Env.Theme) + { + case Foo.Platform.Env.Themes.Classic: + m_oButtonThemeObject = new ButtonClassicTheme(); + break; + case Foo.Platform.Env.Themes.AeroTheme: + m_oButtonThemeObject = new ButtonAeroTheme(); + break; + case Foo.Platform.Env.Themes.VistaNoAero: + m_oButtonThemeObject = new ButtonVistaNoAeroTheme(); + break; + case Foo.Platform.Env.Themes.XPtheme: + m_oButtonThemeObject = new ButtonXPTheme(); + break; + } + } + public IButtonThemeSetting GetIButtonThemeInterface() { return (IButtonThemeSetting)m_oButtonThemeObject; } + public IButtonIconLocation GetIButtonIconLocation() { return (IButtonIconLocation)m_oButtonThemeObject; } + } +} diff --git a/Settings/MyKeyFile.SNK b/Settings/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/Settings/MyKeyFile.SNK differ diff --git a/Settings/Properties/AssemblyInfo.cs b/Settings/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ac455b6 --- /dev/null +++ b/Settings/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Settings")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Ooganizer")] +[assembly: AssemblyProduct("Settings")] +[assembly: AssemblyCopyright("Copyright © Ooganizer 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a28ce1f1-2b84-42ee-abd8-8230ae6a186c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Settings/Properties/Resources.Designer.cs b/Settings/Properties/Resources.Designer.cs new file mode 100644 index 0000000..e3af3f2 --- /dev/null +++ b/Settings/Properties/Resources.Designer.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Platform.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Foo.Platform.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> + ///<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.ooganizer.com"> + /// <ButtonHook> + /// <AllowedProcessNames> + /// <ProcessName strategy="BrowserResolve" prms="" wcinc="*" wtxtinc="*" versions="6.*;7.*;8.*" bhloc="normal">IEXPLORE.EXE</ProcessName> + /// <ProcessName strategy="FHWinResolve" prms="TopOnly" wcinc="*" wtxtinc="*" versions="11.*;12.*" bhloc="normal">WINWORD.EXE</ProcessName> + /// <P [rest of string was truncated]";. + /// + internal static string AppConfigXML { + get { + return ResourceManager.GetString("AppConfigXML", resourceCulture); + } + } + } +} diff --git a/Settings/Properties/Resources.resx b/Settings/Properties/Resources.resx new file mode 100644 index 0000000..7dbac60 --- /dev/null +++ b/Settings/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\AppConfig.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + \ No newline at end of file diff --git a/Settings/Properties/Settings.Designer.cs b/Settings/Properties/Settings.Designer.cs new file mode 100644 index 0000000..fe8b1ba --- /dev/null +++ b/Settings/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4200 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Foo.Platform.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Settings/Properties/Settings.settings b/Settings/Properties/Settings.settings new file mode 100644 index 0000000..15034e7 --- /dev/null +++ b/Settings/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/Settings/RegPathsConfig.bat b/Settings/RegPathsConfig.bat new file mode 100644 index 0000000..02fe716 --- /dev/null +++ b/Settings/RegPathsConfig.bat @@ -0,0 +1,23 @@ +@rem //-- Author: Daniel Romischer (daniel@romischer.com) +@echo off + +goto :start + +:Usage +echo Use this File to Register Ooganizer Paths in the registry +echo. +echo Syntax: RegPathsConfig "[main ooganizer path]" +echo. +echo Example: RegPathsConfig "C:\Program Files\Ooganizer" +echo. +goto :Exit + +:start +if (%1)==() Goto :Usage + +REG ADD HKLM\Software\Ooganizer /v InstallPath /d %1\ /f +REG ADD HKLM\Software\Ooganizer /v LogPath /d %1\Platform\Logs\ /f +REG ADD HKLM\Software\Ooganizer /v PlatformPath /d %1\Platform\ /f +REG ADD HKLM\Software\Ooganizer /v ServerPath /d %1\Server\ /f + +:Exit \ No newline at end of file diff --git a/Settings/Settings.csproj b/Settings/Settings.csproj new file mode 100644 index 0000000..a716858 --- /dev/null +++ b/Settings/Settings.csproj @@ -0,0 +1,107 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {48D75C4F-2749-48BB-9386-721E0E94C144} + Library + Properties + Foo.Platform + Settings + v2.0 + 512 + + + + + + + + + true + MyKeyFile.SNK + + + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + False + ..\Components\log4net.dll + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + + + + $(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /unregister +$(FrameworkDir)\regasm.exe "$(SolutionDir)target\$(ConfigurationName)\$(TargetFileName)" /tlb:$(TargetName).tlb /codebase + "$(ProjectDir)RegPathsConfig.bat" "$(SolutionDir)target\$(ConfigurationName)" + + \ No newline at end of file diff --git a/Settings/SettingsAcc.cs b/Settings/SettingsAcc.cs new file mode 100644 index 0000000..8cbbc99 --- /dev/null +++ b/Settings/SettingsAcc.cs @@ -0,0 +1,459 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using System.IO; +using System.Reflection; +using Foo.Platform; +using System.Diagnostics; + +namespace Foo.Settings +{ + [Guid("6FBB970D-0825-471e-9839-448FB2B6A842")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + [ComVisible(true)] + public interface IOoganizerSettings + { + // reading in configuration data + configuration ReadConfigXMLFile(); + + // write custom configuration data to default location + void WriteConfigXMLFileDefaultLoc(configuration config); + } + + /// + /// Serializable Xml Object used to store all Configuration data - place any new class objects in here + /// + [Guid("EA2D77C2-AA17-4142-8FA7-7D6FA35316F4")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + [XmlRoot("configuration", Namespace = "http://www.ooganizer.com", IsNullable = false)] + public class configuration + { + // Member Tags <> + public ButtonHookSettings ButtonHook = null; + + /// + /// configuration - Constructor + /// + public configuration() + { + ButtonHook = new ButtonHookSettings(); + } + } + + /// + /// Serializable Xml Object used to store ButtonHookSettings + /// + [Guid("2C055265-715A-4d10-B744-ADCE796BED1C")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + [XmlRoot("ButtonHookSettings", Namespace = "http://www.ooganizer.com", IsNullable = false)] + public class ButtonHookSettings + { + // Member Tags <> + public AllowedProcessNamesW AllowedProcessNames = null; + public AllowedWindowTitlesW AllowedWindowTitles = null; + public AllowedWindowClassesW AllowedWindowClasses = null; + public LoggingSettings LogSettings = null; + + /// + /// AllowedProcessNames - (Wrapper) around ArrayList to work with COM and XML + /// + [Guid("06403D5A-E309-42d3-B639-1F9DB99880A4")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class AllowedProcessNamesW + { + private ArrayList m_ArrayList; + public AllowedProcessNamesW() + { + m_ArrayList = new ArrayList(); + } + + [XmlElement("ProcessName")] + public ProcessName[] ProcessNames + { + get + { + ProcessName[] processNames = new ProcessName[m_ArrayList.Count]; + m_ArrayList.CopyTo(processNames); + return processNames; + } + set + { + if (value == null) return; + ProcessName[] processNames = (ProcessName[])value; + m_ArrayList.Clear(); + foreach (ProcessName processName in processNames) + m_ArrayList.Add(processName); + } + } + + public int AddProcessName(ProcessName processName) + { + return m_ArrayList.Add(processName); + } + } + + [Guid("EC4E542F-2877-4bb4-8FEF-30F1A1C1B53B")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class ProcessName + { + public ProcessName() + { + this.CustomBHTop = 0; + this.CustomBHRight = 0; + } + + public ProcessName(string ProcessExe, string Resolver, string ResolverPrms, string Launcher, string Closer, string ShowHider, string Versions, int CustomBHTop, int CustomBHRight) + { + this._ProcessExe = ProcessExe; + this.Resolver = Resolver; + this.ResolverPrms = ResolverPrms; + this.Launcher = Launcher; + this.Closer = Closer; + this.ShowHider = ShowHider; + this.Versions = Versions; + this.CustomBHTop = CustomBHTop; + this.CustomBHRight = CustomBHRight; + } + + private string _ProcessExe; + [XmlText] + public string ProcessExe + { + get + { + if (!String.IsNullOrEmpty(_ProcessExe)) + return _ProcessExe.ToUpper(); + else + return String.Empty; + } + set + { + _ProcessExe = value; + } + } + + [XmlAttribute("Resolver")] + public string Resolver; + + [XmlAttribute("ResolverPrms")] + public string ResolverPrms; + + [XmlAttribute("Launcher")] + public string Launcher; + + [XmlAttribute("Closer")] + public string Closer; + + [XmlAttribute("ShowHider")] + public string ShowHider; + + [XmlAttribute("Versions")] + public string Versions; + + [XmlAttribute("CustomBHTop")] + public int CustomBHTop; + + [XmlAttribute("CustomBHRight")] + public int CustomBHRight; + } + + /// + /// AllowedWindowTitles - (Wrapper) around ArrayList to work with COM and XML + /// + [Guid("5B9CC560-9E53-4ae2-8701-E60F99A9A80D")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class AllowedWindowTitlesW + { + private ArrayList m_ArrayList; + public AllowedWindowTitlesW() + { + m_ArrayList = new ArrayList(); + m_ArrayList.Add(""); + } + [XmlElement("WindowTitle")] + public string[] WindowTitle + { + get + { + string[] windowTitles = new string[m_ArrayList.Count]; + m_ArrayList.CopyTo(windowTitles); + return windowTitles; + } + set + { + if (value == null) return; + string[] windowTitles = (string[])value; + m_ArrayList.Clear(); + foreach (string windowTitle in windowTitles) + m_ArrayList.Add(windowTitle); + } + } + } + + /// + /// AllowedWindowClasses - (Wrapper) around ArrayList to work with COM and XML + /// + [Guid("FE3ECBC4-9082-43b5-8274-7DC3A4FB4855")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class AllowedWindowClassesW + { + private ArrayList m_ArrayList; + public AllowedWindowClassesW() + { + m_ArrayList = new ArrayList(); + m_ArrayList.Add(""); + } + + [XmlElement("WindowClass")] + public string[] WindowClass + { + get + { + string[] windowClasses = new string[m_ArrayList.Count]; + m_ArrayList.CopyTo(windowClasses); + return windowClasses; + } + set + { + if (value == null) return; + string[] windowClasses = (string[])value; + m_ArrayList.Clear(); + foreach (string windowClass in windowClasses) + m_ArrayList.Add(windowClass); + } + } + } + + /// + /// LoggingSettings = Set Log Settings (Location & Detail) for ButtonHook + /// + [Guid("A5A6EBA5-DC51-4bba-B7DC-0202153F57DF")] + [ClassInterface(ClassInterfaceType.AutoDual)] + [ComVisible(true)] + public class LoggingSettings + { + public uint LoggingDetail; + + private string _LogPath; + public string LogPath + { + get + { + if (!String.IsNullOrEmpty(_LogPath)) + return Platform.Env.GetLogDirectory(); + else + return _LogPath; + } + set + { + try + { + if (Directory.Exists(value)) + _LogPath = value; + } + catch(Exception){} + } + } + + public LoggingSettings() + { + _LogPath = String.Empty; + LoggingDetail = (int)_LoggingDetail.LOGGING_NONE; + } + + // same enum Definition in ButtonHook + public enum _LoggingDetail { LOGGING_NONE = 0, LOGGING_LOW = 1, LOGGING_MEDIUM = 2, LOGGING_HIGH = 3}; + } + + /// + /// ButtonHookSettings - Constructor + /// + public ButtonHookSettings() + { + AllowedProcessNames = new AllowedProcessNamesW(); + AllowedWindowTitles = new AllowedWindowTitlesW(); + AllowedWindowClasses = new AllowedWindowClassesW(); + LogSettings = new LoggingSettings(); + } + } + + [Guid("80adff74-7124-42e6-ac2c-e19f51a47432")] + [ClassInterface(ClassInterfaceType.None)] + [ProgId("Ooganizer.SettingsAcc")] + [ComVisible(true)] + public class OoganizerSettingsAcc : IOoganizerSettings + { + private XmlSerializer m_ConfigSerializer = null; + public const string DEFAULT_CONFIG_XML_FILE_NAME = "AppConfig.xml"; + private string m_AssemblyLocation = "";// location of running assembly + private configuration m_Configuration; // holds the latest configuration read in or written out, + // for easy access to the configuration + + /// + /// Construcs the SettingsAccessor Object, Responsible for + /// interfacing with the App.Config file + /// + public OoganizerSettingsAcc() + { + m_ConfigSerializer = new XmlSerializer(typeof(configuration)); + + if (m_ConfigSerializer == null) + throw new OutOfMemoryException(); + + // The location of this assembly is in the Platform Directory + m_AssemblyLocation = Platform.InstallationSpec.InstallPath; + } + + #region IOoganizerSettings + + /// + /// Reads in the Config File from the Resource. + /// + /// the configuration object + public configuration ReadConfigXMLFile() + { + string strFileNameWithPath = m_AssemblyLocation + '\\' + DEFAULT_CONFIG_XML_FILE_NAME; + + // If a physical xml file exists in the current directory (allow it to overwrite our settings) + if (File.Exists(strFileNameWithPath + '\\' + DEFAULT_CONFIG_XML_FILE_NAME)) + { + return ReadConfigXMLFile(strFileNameWithPath, false); + } + else + { + // Else force reading of the Resource + return ReadConfigXMLFile(strFileNameWithPath, true); + } + } + + /// + /// Writes the specified configruation to the default location and configuration file + /// + /// configuration object to write out + public void WriteConfigXMLFileDefaultLoc(configuration config) + { + string strFileNameWithPath = m_AssemblyLocation + '\\' + DEFAULT_CONFIG_XML_FILE_NAME; + WriteConfigXMLFile(strFileNameWithPath, config); + } + + #endregion + + #region XML Writer Functions - useful for * Development and Debugging * + + /// + /// Writes the specified configuration to the specified configuration file + /// + /// absolute path to file + /// configuration object to write out + public void WriteConfigXMLFile(string strFileNameWithPath, configuration config) + { + try + { + if (!Directory.Exists(Path.GetDirectoryName(strFileNameWithPath))) + { + Log.Error(string.Format("{0}() - Directory for {1} does not exist", MethodBase.GetCurrentMethod().Name, strFileNameWithPath)); + return; + } + + TextWriter writer = new StreamWriter(strFileNameWithPath); + m_ConfigSerializer.Serialize(writer, config); + m_Configuration = config; + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + return; + } + } + + /// + /// Use this to write a blank xml config file that you can then use + /// to store your configuration + /// + /// absolute path to file + public void WriteBlankConfigXMLFile(string strFileNameWithPath) + { + try + { + if (!Directory.Exists(Path.GetDirectoryName(strFileNameWithPath))) + { + Log.Error(string.Format("{0}() - Directory for {1} does not exist", MethodBase.GetCurrentMethod().Name, strFileNameWithPath)); + return; + } + + TextWriter writer = new StreamWriter(strFileNameWithPath); + configuration settings = new configuration(); + m_ConfigSerializer.Serialize(writer, settings); + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + return; + } + } + + #endregion + + #region Main ReadConfig Function - Does most of the work + + /// + /// Reads in the config file from the passed in location or from the Resource + /// + /// absolute path to file (not used when bReadFromResource is true) + /// true to read Resource XML, false to read from passed in strFileNameWithPath + /// + private configuration ReadConfigXMLFile(string strFileNameWithPath, bool bReadFromResource) + { + const string SETTING_XML_RESOURCE_NAME = "Foo.Platform.AppConfig.xml"; + try + { + + if (bReadFromResource) + { + Assembly assembly = Assembly.GetExecutingAssembly(); + + // * Debugging Only * Make sure resource Name exists + #if DEBUG + string[] resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); + bool bFound = false; + foreach (string resourceName in resourceNames) + { + if (resourceName == SETTING_XML_RESOURCE_NAME) + bFound = true; + } + Debug.Assert(bFound); + #endif + + TextReader reader = new StreamReader(assembly.GetManifestResourceStream(SETTING_XML_RESOURCE_NAME)); + m_Configuration = (configuration)m_ConfigSerializer.Deserialize(reader); + return m_Configuration; + } + else + { + TextReader reader = new StreamReader(strFileNameWithPath); + m_Configuration = (configuration)m_ConfigSerializer.Deserialize(reader); + return m_Configuration; + } + } + catch (Exception e) + { + Log.Error(string.Format("{0}() - error thrown", MethodBase.GetCurrentMethod().Name), e); + throw (new Exception(e.Message)); + } + } + + #endregion + + // Declare the Log4net Variable + private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); + } +} diff --git a/Settings/app.config b/Settings/app.config new file mode 100644 index 0000000..b7db281 --- /dev/null +++ b/Settings/app.config @@ -0,0 +1,3 @@ + + + diff --git a/WorkspaceMgr/Closers/Closer_Generic.cs b/WorkspaceMgr/Closers/Closer_Generic.cs new file mode 100644 index 0000000..25c5a04 --- /dev/null +++ b/WorkspaceMgr/Closers/Closer_Generic.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform.Win32; + +namespace Foo.WorkspaceMgr.Closers +{ + internal class Closer_Generic : IClose + { + #region IClose Members + + /// + /// Sends a WM_QUERYENDSESSION to the Window that the Artifact Belongs To + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryClose(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + // To Do: Must get hWnd From RAT + IntPtr hWnd = IntPtr.Zero; + if (Win32Functions.SendMessage(hWnd, (int)WindowMessage.WM_QUERYENDSESSION, IntPtr.Zero, IntPtr.Zero) != 0) + { + return FuncDepBoolType.Success; + } + else + { + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Sends a WM_Close to the Window that the Artifact Belongs To + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IClose(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + // To Do: Must get hWnd From RAT + IntPtr hWnd = IntPtr.Zero; + if (Win32Functions.SendMessage(hWnd, (int)WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + { + return FuncDepBoolType.Success; + } + else + { + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/Closers/Closer_IE.cs b/WorkspaceMgr/Closers/Closer_IE.cs new file mode 100644 index 0000000..28738d0 --- /dev/null +++ b/WorkspaceMgr/Closers/Closer_IE.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform.Win32; + +namespace Foo.WorkspaceMgr.Closers +{ + internal class Closer_IE : IClose + { + #region IClose Members + + /// + /// + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryClose(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + // To Do: Must get hWnd From RAT + //IntPtr hWnd = IntPtr.Zero; + //if (Win32Functions.SendMessage(hWnd, (int)WindowMessage.WM_QUERYENDSESSION, IntPtr.Zero, IntPtr.Zero) != 0) + //{ + // return FuncDepBoolType.Success; + //} + //else + //{ + // return FuncDepBoolType.Failed; + //} + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Sends a WM_Close to the Window that the Artifact Belongs To + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IClose(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + // To Do: Must get hWnd From RAT + //IntPtr hWnd = IntPtr.Zero; + //if (Win32Functions.SendMessage(hWnd, (int)WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + //{ + // return FuncDepBoolType.Success; + //} + //else + //{ + // return FuncDepBoolType.Failed; + //} + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/Closers/Closer_Office.cs b/WorkspaceMgr/Closers/Closer_Office.cs new file mode 100644 index 0000000..a623af3 --- /dev/null +++ b/WorkspaceMgr/Closers/Closer_Office.cs @@ -0,0 +1,625 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Reflection; + +using Foo.Platform; +using Foo.Platform.Win32; +using System.Diagnostics; +using System.Runtime.InteropServices; + +//// +// Ignore 'Ambiguity' warning message, seems like no way around those +//// +#pragma warning disable 0467 + +namespace Foo.WorkspaceMgr.Closers +{ + class Closer_Office : IClose + { + + #region IClose Members + + /// + /// Dispatches the QueryClose Request to the Proper Office Closer + /// + /// + /// + public FuncDepBoolType IQueryClose(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return QueryClose_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return QueryClose_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return QueryClose_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return QueryClose_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return QueryClose_MSVisio(strArtifactLocation); + + case "MSACCESS.EXE": + return QueryClose_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + /// + /// Dispatches the Close Request to the Proper Office Closer + /// + /// + /// + public FuncDepBoolType IClose(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return Close_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return Close_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return Close_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return Close_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return Close_MSVisio(strArtifactLocation); + + case "MSACCESS.EXE": + return Close_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + #endregion + + #region Microsoft Word IClose Members + + public const string Word_ProgId = "Word.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSWord(string strArtifactLocation) + { + try + { + // Microsoft.Office.Interop.Word.Application app = null; + // app = Win32Functions.GetCOMObject(Word_ProgId) as Microsoft.Office.Interop.Word.Application; + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (doc.Saved) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + + //**** Another Way Stored here for Later **** + // may be this is helpful.. + //using ComTypes = System.Runtime.InteropServices.ComTypes; + //ComTypes.IPersistFile persistFile = (ComTypes.IPersistFile)document; + //Checks an object for changes since it was last saved to its current file. + //if (persistFile.IsDirty) + //{ + //do your stuff + //} + return FuncDepBoolType.Failed; + } + + /// + /// *** Technically ** Here we want to close the Word Document (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSWord(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Found the document to close * Close it Without Prompting * + object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdSaveChanges; + object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat; + object routeDocument = false; + var app = doc.Application; + + // Let's get the Window that belongs to this document + Microsoft.Office.Interop.Word.Window docWindow = null; + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + docWindow = window; + } + } + + //Object missing = Missing.Value; + doc.Close(ref saveOption, ref originalFormat, ref routeDocument); + Marshal.FinalReleaseComObject(doc); // force clean-up + + // Close the Window + if (docWindow != null) + docWindow.Close(ref saveOption, ref routeDocument); + + // Close Word if this is the Last Document Instance + if (app.Documents.Count == 0) + { + app.Quit(ref saveOption, ref originalFormat, ref routeDocument); + Marshal.FinalReleaseComObject(app); // force clean-up, closes Process for sure + } + + return FuncDepBoolType.Success; + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft Excel IClose Members + + public const string Excel_ProgId = "Excel.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if(book.Saved) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// *** Technically ** Here we want to close the Excel Workbook (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // In case there is a running rogue excel process left open, + // we can always force it to close by closing the process + // int hWnd = app.Hwnd; + // Process process = Win32Functions.GetProcessFromHandle((IntPtr) hWnd); + var app = book.Application; + + // Close the Workbook + book.Close(true, strArtifactLocation, false); + Marshal.FinalReleaseComObject(book); // force clean-up + + // Close Excel if this is the last Workbook + if (app.Workbooks.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, should clean up excel process + //process.Close(); + } + return FuncDepBoolType.Success; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft PowerPoint IClose Members + + public const string PowerPoint_ProgId = "PowerPoint.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + //Microsoft.Office.Interop.PowerPoint.Application app = null; + //app = Win32Functions.GetCOMObject(PowerPoint_ProgId) as Microsoft.Office.Interop.PowerPoint.Application; + //foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in app.Presentations) + + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Saved) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + return FuncDepBoolType.Success; + + case Microsoft.Office.Core.MsoTriState.msoFalse: + return FuncDepBoolType.Failed; + } + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// *** Technically ** Here we want to close the Word Document (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + //Microsoft.Office.Interop.PowerPoint.Application app = null; + //app = Win32Functions.GetCOMObject(PowerPoint_ProgId) as Microsoft.Office.Interop.PowerPoint.Application; + //foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in app.Presentations) + + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = presentation.Application; + + // Save this Presentation + presentation.Save(); + + // Close this Presentation + presentation.Close(); + + Marshal.FinalReleaseComObject(presentation); // force clean-up + + // Close PowerPoint if there are no more Presentations + if (app.Presentations.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up, kill application for sure + } + + return FuncDepBoolType.Success; + } + } + return FuncDepBoolType.Failed; + + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft Publisher IClose Members + + public const string Publisher_ProgId = "Publisher.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSPublisher(string strArtifactLocation) + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + if (pubDoc.Saved) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + } + return FuncDepBoolType.Success; + } + + /// + /// *** Technically ** Here we want to close the Word Document (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSPublisher(string strArtifactLocation) + { + + IntPtr hWnd = IntPtr.Zero; + try + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + pubDoc.Save(); + + // Get the Handle + hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + goto FOUND_DOCUMENT_HWND; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + FOUND_DOCUMENT_HWND: + // Get the Process + Process process = Win32Functions.GetProcessFromHandle(hWnd); + + // Send Close Message + if (Win32Functions.SendMessage((IntPtr)hWnd, (int)WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == 0) + { + process.Kill(); + return FuncDepBoolType.Success; + } + else + { + return FuncDepBoolType.Failed; + } + } + + #endregion + + #region Microsoft Visio IClose Members + + public const string Visio_ProgId = "Visio.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSVisio(string strArtifactLocation) + { + + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + if (doc.Saved) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + + return FuncDepBoolType.Success; + } + + /// + /// *** Technically ** Here we want to close the Word Document (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSVisio(string strArtifactLocation) + { + + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + doc.Save(); + + var app = doc.Application; + + doc.Close(); + Marshal.FinalReleaseComObject(doc); // Force Clean-up + + if (app.Documents.Count == 0) + { + app.Quit(); + Marshal.FinalReleaseComObject(app); // force clean-up + } + + + return FuncDepBoolType.Success; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + } + } + + return FuncDepBoolType.Success; + } + + #endregion + + #region Microsoft Access IClose Members + + public const string Access_ProgId = "Access.Application"; + + /// + /// To Do : Test This - Let's us know if the user has unsaved data + /// + /// + /// + public FuncDepBoolType QueryClose_MSAccess(string strArtifactLocation) + { + + var RunningAccessApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + return FuncDepBoolType.Success; + } + } + return FuncDepBoolType.Failed; + } + + /// + /// *** Technically ** Here we want to close the Word Document (Not Prompt the user at all) + /// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + /// DOM, however more testing to be done here + /// + /// + /// + public FuncDepBoolType Close_MSAccess(string strArtifactLocation) + { + + var RunningAccessApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps) + { + if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get Handle and Process + IntPtr hWnd = (IntPtr) app.hWndAccessApp(); + Process process = Win32Functions.GetProcessFromHandle((IntPtr)hWnd); + + // Close the database + //app.CloseCurrentDatabase(); + app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll); + Marshal.FinalReleaseComObject(app); // force clean-up + + // Kill the process + process.Kill(); + + return FuncDepBoolType.Success; + } + } + return FuncDepBoolType.Failed; + } + + #endregion + } +} diff --git a/WorkspaceMgr/Closers/IClose.cs b/WorkspaceMgr/Closers/IClose.cs new file mode 100644 index 0000000..d8c5eee --- /dev/null +++ b/WorkspaceMgr/Closers/IClose.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.WorkspaceMgr.Closers +{ + internal interface IClose + { + FuncDepBoolType IQueryClose(string strArtifactLocation); + FuncDepBoolType IClose(string strArtifactLocation); + } +} diff --git a/WorkspaceMgr/Configurations.cs b/WorkspaceMgr/Configurations.cs new file mode 100644 index 0000000..17e9823 --- /dev/null +++ b/WorkspaceMgr/Configurations.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform.Utilities; + +namespace Foo.WorkspaceMgr +{ + public static class Configurations + { + #region Excel 2007 Configuration + + private static string EXCEL_OPTIONS_REGISTRY_LOCATION = "Microsoft\\Office\\12.0\\Excel\\Options"; + + static public void Configure_Excel2007() + { + RegM reg = new RegM(HKEYRoot.CurrentUser, KeySub.Software, EXCEL_OPTIONS_REGISTRY_LOCATION, true); + reg.SetVal_Int("ShowWindowsInTaskbar", 1); + } + + #endregion + + static Configurations() + { + } + + + + } + +} diff --git a/WorkspaceMgr/HelperFunc.cs b/WorkspaceMgr/HelperFunc.cs new file mode 100644 index 0000000..956b656 --- /dev/null +++ b/WorkspaceMgr/HelperFunc.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.WorkspaceMgr +{ + internal static class HelperFunc + { + internal const int DEFAULT_SHOWNHIDE_SLEEP_TIME = 250; + internal const int DEFAULT_CLOSE_SLEEP_TIME = 500; + internal const int DEFAULT_LAUNCH_SLEEP_TIME = 1000; + + /// + /// Depending on the Quality of the Index Optimizations, + /// Return what the best type of action is afterward + /// + internal enum IndexOptimizationQuality + { + Good, + Average, + Poor + } + + // Helper Class for OptimalLaunchIndexesForFileArtifacts + internal class OptimalIndexes + { + public int Index; + public string FileName; + internal OptimalIndexes(int Index, string FileName) + { + this.Index = Index; + this.FileName = FileName; + } + } + + /// + /// + /// + /// + /// + internal static int GetSleepTimeForQuality(IndexOptimizationQuality quality) + { + int nSleepTime = 1350; + switch (quality) + { + case HelperFunc.IndexOptimizationQuality.Good: + nSleepTime = 1350; + break; + + case HelperFunc.IndexOptimizationQuality.Average: + nSleepTime = 1675; + break; + + case HelperFunc.IndexOptimizationQuality.Poor: + nSleepTime = 2000; + break; + } + return nSleepTime; + } + + /// + /// For Launching of File Artifacts we must make sure that artifacts are in an order that allows us + /// to properly resolve them dynamically. When files with the same name get launched too close together, + /// window resolution will become increasingly difficult. + /// + /// a group of artifacts (Only file Artifacts will be processed) + /// an array of indexes that specifies the launch order of all the files in this group + internal static IndexOptimizationQuality OptimalLaunchIndexesForFileArtifacts(ArtifactItem[] artifactItems, out int[] optimalIndexes) + { + + // Step One - If it is a file type, then we get the file name and it's index to put into a list + List optIndex = new List(); + for (int i = 0; i < artifactItems.Length; ++i) + { + if(artifactItems[i].IsFile) + optIndex.Add(new OptimalIndexes(i, artifactItems[i].FileName)); + } + + // Step Two - Sort the List by FileName + optIndex.Sort(delegate(OptimalIndexes o1, OptimalIndexes o2) { return o1.FileName.CompareTo(o2.FileName); }); + + // Step Three - Go thru sorted list and get out all the Singles + List singlesList = new List(); + for (int i = 0; i < optIndex.Count; ++i) + { + bool bIsSingle = true; + bool bCompareUp = ((i > 0) && (i < optIndex.Count)); + bool bCompareDown = (i < (optIndex.Count - 1)); + + if (bIsSingle && bCompareUp) + bIsSingle = (String.Compare(optIndex[i].FileName, optIndex[i - 1].FileName, true) != 0); + + if (bIsSingle && bCompareDown) + bIsSingle = (String.Compare(optIndex[i].FileName, optIndex[i + 1].FileName, true) != 0); + + // If Single - Add To Singles List + if (bIsSingle) + singlesList.Add(i); + } + + // If all items in the List were singles then we are really good to go + // and can exit out of here + if (singlesList.Count == optIndex.Count) + { + // Pass out the Indexes of the Array To The Caller + optimalIndexes = new int[optIndex.Count]; + for (int i = 0; i < optIndex.Count; ++i) + optimalIndexes[i] = optIndex[i].Index; + + // Since there are no doubles - this is a low risk / high quality optimization + return IndexOptimizationQuality.Good; + } + + // Step Four - There are doubles and/or no singles + // ~remove all singles from optIndex + foreach (int index in singlesList) + { + + } + + + + + + // 2) we make a list of all filenames in sorted order (with an index to which artifact it belongs) + + + // 3) we then generate the most optimal list of indexes that we pass out for the caller to use + + foreach (ArtifactItem artifact in artifactItems) + { + + + } + + optimalIndexes = new int[1]; + + return IndexOptimizationQuality.Average; + } + + + + } +} diff --git a/WorkspaceMgr/IWorkspaceMgr.cs b/WorkspaceMgr/IWorkspaceMgr.cs new file mode 100644 index 0000000..22cdf35 --- /dev/null +++ b/WorkspaceMgr/IWorkspaceMgr.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; + +namespace Foo.WorkspaceMgr +{ + public interface IWorkspaceMgr + { + // Artifact Related + bool LaunchArtifact(ArtifactItem artifactItem); + bool CloseArtifact(ArtifactItem artifactItem); + bool HideShowArtifact(ArtifactItem artifactItem, bool bShow); + + // Workspace Related + bool LaunchWorkspace(string WorkspaceName); + bool CloseWorkspace(string WorkspaceName); + bool HideShowWorkspace(string WorkspaceName, bool bShow); + } +} diff --git a/WorkspaceMgr/Launchers/ILaunch.cs b/WorkspaceMgr/Launchers/ILaunch.cs new file mode 100644 index 0000000..70b1b91 --- /dev/null +++ b/WorkspaceMgr/Launchers/ILaunch.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.WorkspaceMgr.Launchers +{ + internal interface ILaunch + { + FuncDepBoolType IQueryLaunch(string strArtifactLocation); + FuncDepBoolType ILaunch(string strArtifactLocation); + } +} diff --git a/WorkspaceMgr/Launchers/Launcher_Excel.cs b/WorkspaceMgr/Launchers/Launcher_Excel.cs new file mode 100644 index 0000000..3d52e87 --- /dev/null +++ b/WorkspaceMgr/Launchers/Launcher_Excel.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +using Foo.Platform.Win32; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Reflection; + +namespace Foo.WorkspaceMgr.Launchers +{ + internal class Launcher_Excel : ILaunch + { + #region ILaunch Members + + /// + /// Checks to see if the file exists in the system i.e. can be reached over + /// the network. if FileExists fails, we shouldn't be able to launch it. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryLaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + if (File.Exists(strArtifactLocation)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.ArtifactLocationUnavailable; + } + else + { + return FuncDepBoolType.ParametersInvalid; + } + } + + public const string Excel_ProgId = "Excel.Application"; + + /// + /// Generic Launcher should be able to handle any file type. Launched the .Net Way. + /// ~this is the same as if the User clicks on the file. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType ILaunch(string strArtifactLocation) + { + Microsoft.Office.Interop.Excel.Application app = null; + app = new Microsoft.Office.Interop.Excel.Application(); + + // Mark the Application as visible + app.Visible = true; + + app.Workbooks.Open(strArtifactLocation, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, + Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value ); + + // Keep Track of all our Excel Instances + ///WorkspaceState.Launched_ExcelInstances.Add(app); + + return FuncDepBoolType.Success; + + //if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + //{ + // Process.Start(strArtifactLocation); + //} + //return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + + + + + + ///// + ///// To Do : Test This - Let's us know if the user has unsaved data + ///// + ///// + ///// + //public FuncDepBoolType QueryClose_MSExcel(string strArtifactLocation) + //{ + // try + // { + + + // foreach (Microsoft.Office.Interop.Excel.Workbook book in app.Workbooks) + // { + // if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + // { + // if (book.Saved) + // return FuncDepBoolType.Success; + // else + // return FuncDepBoolType.Failed; + // } + // } + // } + // catch (Exception e) + // { + // string message = e.Message; + // message = message + ""; + // // TODO: Log Something here + // return FuncDepBoolType.ErrorThrown; + // } + + // return FuncDepBoolType.Failed; + //} + + ///// + ///// *** Technically ** Here we want to close the Excel Workbook (Not Prompt the user at all) + ///// **** we could close it with a WM_CLOSE or WM_SCLOSE or with the DOM. ~for now it's the + ///// DOM, however more testing to be done here + ///// + ///// + ///// + //public FuncDepBoolType Close_MSExcel(string strArtifactLocation) + //{ + // try + // { + // Microsoft.Office.Interop.Excel.Application app = null; + // app = Win32Functions.GetCOMObject(Excel_ProgId) as Microsoft.Office.Interop.Excel.Application; + + // // For Debugging + // //int nCount = app.Workbooks.Count; + + // foreach (Microsoft.Office.Interop.Excel.Workbook book in app.Workbooks) + // { + // if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + // { + // book.Close(true, strArtifactLocation, false); + + // // Close Excel if this is the last Workbook + // if (app.Workbooks.Count == 0) + // app.Quit(); + + // return FuncDepBoolType.Success; + // } + // } + // } + // catch (Exception e) + // { + // string message = e.Message; + // message = message + ""; + // // TODO: Log Something here + // return FuncDepBoolType.ErrorThrown; + // } + + // return FuncDepBoolType.Failed; + //} + + + } +} diff --git a/WorkspaceMgr/Launchers/Launcher_Generic.cs b/WorkspaceMgr/Launchers/Launcher_Generic.cs new file mode 100644 index 0000000..ed8d92f --- /dev/null +++ b/WorkspaceMgr/Launchers/Launcher_Generic.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +using Foo.Platform.Win32; +using System.Runtime.InteropServices; +using System.Diagnostics; + +namespace Foo.WorkspaceMgr.Launchers +{ + internal class Launcher_Generic : ILaunch + { + #region ILaunch Members + + /// + /// Checks to see if the file exists in the system i.e. can be reached over + /// the network. if FileExists fails, we shouldn't be able to launch it. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryLaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + if (File.Exists(strArtifactLocation)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.ArtifactLocationUnavailable; + } + else + { + return FuncDepBoolType.ParametersInvalid; + } + } + + /// + /// Generic Launcher should be able to handle any file type. Launched the .Net Way. + /// ~this is the same as if the User clicks on the file. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType ILaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + Process.Start(strArtifactLocation); + return FuncDepBoolType.Success; + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/Launchers/Launcher_Shell.cs b/WorkspaceMgr/Launchers/Launcher_Shell.cs new file mode 100644 index 0000000..9807d24 --- /dev/null +++ b/WorkspaceMgr/Launchers/Launcher_Shell.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +using Foo.Platform.Win32; +using System.Runtime.InteropServices; +using System.Diagnostics; + +namespace Foo.WorkspaceMgr.Launchers +{ + internal class Launcher_Shell : ILaunch + { + #region ILaunch Members + + /// + /// Checks to see if the file exists in the system i.e. can be reached over + /// the network. if FileExists fails, we shouldn't be able to launch it. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryLaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + if (File.Exists(strArtifactLocation)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.ArtifactLocationUnavailable; + } + else + { + return FuncDepBoolType.ParametersInvalid; + } + } + + /// + /// Generic Launcher should be able to handle any file type using Shell Execute + /// ~This is NOT the same as Process.start(). When using ShellExecute, Excel workbooks + /// launch in a different window (and for some reason Don't SHOW UP in the Excel DOM) + /// ~this is why this is broken out (more testing is needed) + /// + /// location of the path + file to launch + /// + public FuncDepBoolType ILaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + // Shellexecute works almost just like process.start except for the limitation + // mentioned: + // We could do process start but doing so means all excel docs open in the same + // excel window (just like powerpoint does) ~this may or may not be desirable + // ~excel docs won't show in the DOM, after being launched this way ~ - very odd + bool bIsValidExe = false; + string strExeOrDllPath = string.Empty; + bool bFound = Win32_WrapperFunc.FindExeOrDll(strArtifactLocation, out strExeOrDllPath, out bIsValidExe); + + const int SEE_MASK_NOCLOSEPROCESS = 0x40; + ShellExecuteInfo sei = new ShellExecuteInfo(); + sei.cbSize = Marshal.SizeOf(sei); + sei.lpVerb = "open"; + sei.lpParameters = '\"' + strArtifactLocation + '\"'; + sei.nShow = (int)WindowAction.SW_SHOWNORMAL; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + + // Use Shell32 or Explorer to launch the artifact + if (bFound && bIsValidExe) + sei.lpFile = strExeOrDllPath; + else + sei.lpFile = '\"' + Win32_WrapperFunc.GetWindowsPath() + "\\explorer.exe" + '\"'; + + if (Win32Functions.ShellExecuteEx(ref sei)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/Launchers/Launcher_Visio.cs b/WorkspaceMgr/Launchers/Launcher_Visio.cs new file mode 100644 index 0000000..5aa7c57 --- /dev/null +++ b/WorkspaceMgr/Launchers/Launcher_Visio.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +using Foo.Platform.Win32; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Reflection; + +namespace Foo.WorkspaceMgr.Launchers +{ + internal class Launcher_Visio : ILaunch + { + #region ILaunch Members + + /// + /// Checks to see if the file exists in the system i.e. can be reached over + /// the network. if FileExists fails, we shouldn't be able to launch it. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryLaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + if (File.Exists(strArtifactLocation)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.ArtifactLocationUnavailable; + } + else + { + return FuncDepBoolType.ParametersInvalid; + } + } + + public const string Excel_ProgId = "Visio.Application"; + + /// + /// Generic Launcher should be able to handle any file type. Launched the .Net Way. + /// ~this is the same as if the User clicks on the file. + /// + /// location of the path + file to launch + /// + public FuncDepBoolType ILaunch(string strArtifactLocation) + { + Microsoft.Office.Interop.Visio.Application app = null; + app = new Microsoft.Office.Interop.Visio.Application(); + + // Mark the Application as visible + app.Visible = true; + + app.Documents.Open(strArtifactLocation); + + // Keep Track of all our Excel Instances + ///WorkspaceState.Launched_ExcelInstances.Add(app); + + return FuncDepBoolType.Success; + + //if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + //{ + // Process.Start(strArtifactLocation); + //} + //return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + } +} diff --git a/WorkspaceMgr/Launchers/Launcher_Web.cs b/WorkspaceMgr/Launchers/Launcher_Web.cs new file mode 100644 index 0000000..6099b19 --- /dev/null +++ b/WorkspaceMgr/Launchers/Launcher_Web.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; + +namespace Foo.WorkspaceMgr.Launchers +{ + class Launcher_Web : ILaunch + { + #region ILaunch Members + + /// + /// Checks to see if the url is valid + /// ~~( We could even check if the webpage is available here!!!) ~to do later? + /// + /// url to launch + /// + public FuncDepBoolType IQueryLaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + if (Uri.IsWellFormedUriString(strArtifactLocation, UriKind.Absolute)) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Generic Launcher should be able to handle any url type + /// + /// url to launch + public FuncDepBoolType ILaunch(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3)) + { + Process.Start(strArtifactLocation); + return FuncDepBoolType.Success; + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/MyKeyFile.SNK b/WorkspaceMgr/MyKeyFile.SNK new file mode 100644 index 0000000..8bc8162 Binary files /dev/null and b/WorkspaceMgr/MyKeyFile.SNK differ diff --git a/WorkspaceMgr/Properties/AssemblyInfo.cs b/WorkspaceMgr/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..654523c --- /dev/null +++ b/WorkspaceMgr/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WorkspaceMgr")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WorkspaceMgr")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5f6d39ae-f75e-447b-b3c0-e1abb34b4fc8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WorkspaceMgr/ShowNHide/IShowNHide.cs b/WorkspaceMgr/ShowNHide/IShowNHide.cs new file mode 100644 index 0000000..fbee3e5 --- /dev/null +++ b/WorkspaceMgr/ShowNHide/IShowNHide.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.WorkspaceMgr.Hiders +{ + internal interface IShowNHide + { + FuncDepBoolType IQueryShow(string strArtifactLocation); + FuncDepBoolType IShow(string strArtifactLocation); + + FuncDepBoolType IQueryHide(string strArtifactLocation); + FuncDepBoolType IHide(string strArtifactLocation); + } +} diff --git a/WorkspaceMgr/ShowNHide/ShowNHide_Generic.cs b/WorkspaceMgr/ShowNHide/ShowNHide_Generic.cs new file mode 100644 index 0000000..174ebf6 --- /dev/null +++ b/WorkspaceMgr/ShowNHide/ShowNHide_Generic.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform.Win32; + +namespace Foo.WorkspaceMgr.Hiders +{ + internal class ShowNHide_Generic : IShowNHide + { + + #region IShowNHide Members + + /// + /// Default behavior is to just return success ** Should Check if Window is hidden?/shown??? + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryShow(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + return FuncDepBoolType.Success; + + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Calls ShowWindow to Show the Window + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IShow(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + IntPtr hWnd = IntPtr.Zero; // ToDo : Implement RAT + Win32Functions.ShowWindow(hWnd, (int)WindowAction.SW_SHOW); + return FuncDepBoolType.Success; + } + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Default behavior is to just return success ** Should Check if Window is hidden?/shown??? + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IQueryHide(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + return FuncDepBoolType.Success; + + return FuncDepBoolType.ParametersInvalid; + } + + /// + /// Calls ShowWindow to Hide the Window + /// + /// location of the path + file to launch + /// + public FuncDepBoolType IHide(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + IntPtr hWnd = IntPtr.Zero; // ToDo : Implement RAT + Win32Functions.ShowWindow(hWnd, (int)WindowAction.SW_HIDE); + return FuncDepBoolType.Success; + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + } +} diff --git a/WorkspaceMgr/ShowNHide/ShowNHide_Office.cs b/WorkspaceMgr/ShowNHide/ShowNHide_Office.cs new file mode 100644 index 0000000..d1234d7 --- /dev/null +++ b/WorkspaceMgr/ShowNHide/ShowNHide_Office.cs @@ -0,0 +1,847 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform.Win32; +using System.Runtime.InteropServices; + +namespace Foo.WorkspaceMgr.Hiders +{ + internal class ShowNHide_Office : IShowNHide + { + #region IShowNHide Members + + public FuncDepBoolType IQueryShow(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return QueryShow_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return QueryShow_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return QueryShow_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return QueryShow_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return QueryShow_MSVisio(strArtifactLocation); + + //case "ACCESS.EXE": + // return QueryClose_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + public FuncDepBoolType IShow(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return Show_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return Show_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return Show_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return Show_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return Show_MSVisio(strArtifactLocation); + + //case "ACCESS.EXE": + // return QueryClose_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + public FuncDepBoolType IQueryHide(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return QueryHide_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return QueryHide_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return QueryHide_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return QueryHide_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return QueryHide_MSVisio(strArtifactLocation); + + //case "ACCESS.EXE": + // return QueryClose_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + public FuncDepBoolType IHide(string strArtifactLocation) + { + switch (Win32_WrapperFunc.GetRegisteredExeForFile(strArtifactLocation)) + { + case "WINWORD.EXE": + return Hide_MSWord(strArtifactLocation); + + case "EXCEL.EXE": + return Hide_MSExcel(strArtifactLocation); + + case "POWERPNT.EXE": + return Hide_MSPowerPoint(strArtifactLocation); + + case "MSPUB.EXE": + return Hide_MSPublisher(strArtifactLocation); + + case "VISIO.EXE": + return Hide_MSVisio(strArtifactLocation); + + //case "ACCESS.EXE": + // return QueryClose_MSAccess(strArtifactLocation); + } + return FuncDepBoolType.FunctionallityNotSupported; + } + + #endregion + + #region Microsoft Word IShowNHide Members + + FuncDepBoolType QueryShow_MSWord(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if(window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if(!window.Visible) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Show_MSWord(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (!window.Visible) + { + window.Visible = true; + return FuncDepBoolType.Success; + } + else + { + return FuncDepBoolType.Failed; + } + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType QueryHide_MSWord(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (window.Visible) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Hide_MSWord(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningWordDocuments = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Word.Document doc in RunningWordDocuments) + { + foreach (Microsoft.Office.Interop.Word.Window window in doc.Windows) + { + if (window.Document.FullName.ToLower() == strArtifactLocation.ToLower()) + { + if (window.Visible) + { + window.Visible = false; + return FuncDepBoolType.Success; + } + else + { + return FuncDepBoolType.Failed; + } + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft Excel IShowNHide Members + + FuncDepBoolType QueryShow_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + if (!app.Visible && bIsTheOnlyDocumentInApp) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Show_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + if (!app.Visible && bIsTheOnlyDocumentInApp) + { + app.Visible = true; + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType QueryHide_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + if (app.Visible && bIsTheOnlyDocumentInApp) + { + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Hide_MSExcel(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningExcelWorkbooks = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Excel.Workbook book in RunningExcelWorkbooks) + { + if (book.FullName.ToLower() == strArtifactLocation.ToLower()) + { + var app = book.Application; + + bool bIsTheOnlyDocumentInApp = (app.Workbooks.Count == 1); + + // We could potentially not hide the window but instead just minimize the selected workbook + // ~have to learn + //if (!bIsTheOnlyDocumentInApp) + //{ + // foreach (Microsoft.Office.Interop.Excel.Window window in book.Windows) + // { + // window.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized; + // } + //} + + if (app.Visible && bIsTheOnlyDocumentInApp) + { + app.Visible = false; + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + } + return FuncDepBoolType.ArtifactLocationUnavailable; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft PowerPoint IShowNHide Members + + FuncDepBoolType QueryShow_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + return FuncDepBoolType.Failed; + + case Microsoft.Office.Core.MsoTriState.msoFalse: + return FuncDepBoolType.Success; + } + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Show_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + return FuncDepBoolType.Failed; + + case Microsoft.Office.Core.MsoTriState.msoFalse: + { + //presentation.Application.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; + + Win32Functions.ShowWindow((IntPtr)presentation.Application.HWND, (int)WindowAction.SW_SHOW); + + return FuncDepBoolType.Success; + } + } + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType QueryHide_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + return FuncDepBoolType.Success; + + case Microsoft.Office.Core.MsoTriState.msoFalse: + return FuncDepBoolType.Failed; + } + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Hide_MSPowerPoint(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + try + { + var RunningPowerPoints = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.PowerPoint.Presentation presentation in RunningPowerPoints) + { + if (presentation.FullName.ToLower() == strArtifactLocation.ToLower()) + { + switch (presentation.Application.Visible) + { + case Microsoft.Office.Core.MsoTriState.msoTrue: + { + //presentation.Application.Visible = Microsoft.Office.Core.MsoTriState.msoFalse; + //foreach (Microsoft.Office.Interop.PowerPoint.DocumentWindow docWindow in presentation.Windows) + //{ + // //docWindow. + //} + + Win32Functions.ShowWindow((IntPtr) presentation.Application.HWND, (int)WindowAction.SW_HIDE); + return FuncDepBoolType.Success; + } + + case Microsoft.Office.Core.MsoTriState.msoFalse: + { + return FuncDepBoolType.Failed; + } + } + } + } + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + return FuncDepBoolType.ErrorThrown; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + #region Microsoft Publisher IShowNHide Members + + FuncDepBoolType QueryShow_MSPublisher(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + IntPtr hWnd = IntPtr.Zero; + try + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get the Handle + hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + goto FOUND_DOCUMENT_HWND; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + FOUND_DOCUMENT_HWND: + return FuncDepBoolType.Success; // Check Window State... - TO DO Later + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Show_MSPublisher(string strArtifactLocation) + { + IntPtr hWnd = IntPtr.Zero; + try + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + pubDoc.Save(); + + // Get the Handle + hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + goto FOUND_DOCUMENT_HWND; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + FOUND_DOCUMENT_HWND: + + // Send Show Message + Win32Functions.ShowWindow(hWnd, (int)WindowAction.SW_SHOW); + return FuncDepBoolType.Success; + } + + FuncDepBoolType QueryHide_MSPublisher(string strArtifactLocation) + { + if (!String.IsNullOrEmpty(strArtifactLocation)) + { + IntPtr hWnd = IntPtr.Zero; + try + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Get the Handle + hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + goto FOUND_DOCUMENT_HWND; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + FOUND_DOCUMENT_HWND: + return FuncDepBoolType.Success; // Check Window State... - TO DO Later + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Hide_MSPublisher(string strArtifactLocation) + { + IntPtr hWnd = IntPtr.Zero; + try + { + var RunningPublisherApps = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Publisher.Application app in RunningPublisherApps) + { + foreach (Microsoft.Office.Interop.Publisher.Document pubDoc in app.Documents) + { + if (pubDoc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + // Save the Document + pubDoc.Save(); + + // Get the Handle + hWnd = (IntPtr)pubDoc.ActiveWindow.Hwnd; + goto FOUND_DOCUMENT_HWND; + } + } + } + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + FOUND_DOCUMENT_HWND: + + // Send Show Message + Win32Functions.ShowWindow(hWnd, (int)WindowAction.SW_HIDE); + return FuncDepBoolType.Success; + } + + #endregion + + #region Microsoft Visio IShowNHide Members + + FuncDepBoolType QueryShow_MSVisio(string strArtifactLocation) + { + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + bool bIsTheOnlyDocumentInApp = true; // TO DO: (doc.Application.Documents.Count == 1); not working + if (!doc.Application.Visible && bIsTheOnlyDocumentInApp) + return FuncDepBoolType.Success; + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Show_MSVisio(string strArtifactLocation) + { + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + bool bIsTheOnlyDocumentInApp = true; // TO DO - (doc.Application.Documents.Count == 1); not working + if (!doc.Application.Visible && bIsTheOnlyDocumentInApp) + { + doc.Application.Visible = true; + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType QueryHide_MSVisio(string strArtifactLocation) + { + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + bool bIsTheOnlyDocumentInApp = true; // (doc.Application.Documents.Count == 1); // TO DO - not working + if (doc.Application.Visible && bIsTheOnlyDocumentInApp) + { + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + FuncDepBoolType Hide_MSVisio(string strArtifactLocation) + { + var RunningVisioDocs = Win32Functions.GetRunningObjectsOfType(); + foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs) + { + if (doc.FullName.ToLower() == strArtifactLocation.ToLower()) + { + try + { + bool bIsTheOnlyDocumentInApp = true; // (doc.Application.Documents.Count == 1); // TO DO - not working + if (doc.Application.Visible && bIsTheOnlyDocumentInApp) + { + doc.Application.Visible = false; + return FuncDepBoolType.Success; + } + else + return FuncDepBoolType.Failed; + } + catch (Exception e) + { + string message = e.Message; + message = message + ""; + // TODO: Log Something here + } + + break; + } + } + return FuncDepBoolType.ParametersInvalid; + } + + #endregion + + + } +} diff --git a/WorkspaceMgr/WorkspaceMgr.cs b/WorkspaceMgr/WorkspaceMgr.cs new file mode 100644 index 0000000..6917725 --- /dev/null +++ b/WorkspaceMgr/WorkspaceMgr.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; + +using Foo.WorkspaceMgr.Closers; +using Foo.WorkspaceMgr.Hiders; +using Foo.WorkspaceMgr.Launchers; +using System.Reflection; + +namespace Foo.WorkspaceMgr +{ + public class WorkspaceMgr : IWorkspaceMgr + { + #region IWorkspaceMgr Members + + /// + /// Responsible for Launching a single artifact // ToDo: - CHECK RAT if Artifact is already running + /// // ToDo: - Test IEXPLORER LAUNCHER + /// artifact to launch // ToDo: - Figgure out what to do in Error State + /// true if successful, false otherwise + public bool LaunchArtifact(ArtifactItem artifactItem) + { + + AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Interop.Access, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"); + Assembly assembly = Assembly.Load(assemblyName); + + + //if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity) + if (artifactItem.IsLocationValid) + { + // Step One - Create the Launcher Obj + ILaunch launcher = WorkspaceTypeHelpers.CreateLauncherObj(artifactItem); + if (launcher == null) + return false; + + // Step Two - Query if Launching for this Artifact is supported + FuncDepBoolType retVal = launcher.IQueryLaunch(artifactItem.Location); + + // Step Three - launch it if supported + if (retVal == FuncDepBoolType.Success) + { + retVal = launcher.ILaunch(artifactItem.Location); + } + else + { + // * Log error or something and return otherwise * To Do + return false; + } + + // Step Four - if success signal to the db the artifact was launched + if (retVal == FuncDepBoolType.Success) + { + Data.Artifacts.ArtifactWasLaunched(artifactItem); + } + + return (retVal == FuncDepBoolType.Success); + } + return false; + } + + /// + /// Responsible for Closing a single artifact // ToDo: - CHECK RAT if Artifact is running, if so Get Proccess that it is running in!!! ---- + /// // ToDo: - Test Office, Generic, Notepad, IExplore Closers + /// artifact to close // ToDo: - Figgure out what to do in Error State + /// true if successful, false otherwise + public bool CloseArtifact(ArtifactItem artifactItem) + { + if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity) + { + // Step One - Create the Closer Obj + IClose closer = WorkspaceTypeHelpers.CreateCloserObj(artifactItem); + if (closer == null) + return false; + + // Step Two - Query if Closing for this Artifact is possible + FuncDepBoolType retVal = closer.IQueryClose(artifactItem.Location); + + // Step Three - close it if supported + if (retVal == FuncDepBoolType.Success) + { + retVal = closer.IClose(artifactItem.Location); + } + else + { + // * Log error or something and return otherwise * To Do + return false; + } + + return (retVal == FuncDepBoolType.Success); + } + return false; + } + + /// + /// Responsible for Hiding or showing a single artifact // ToDo: - CHECK RAT if Artifact is running, if so Get Proccess that it is running in!!! ---- + /// // ToDo: - Test Office, Generic, Notepad, IExplore Hiders + /// artifact to hide // ToDo: - Figgure out what to do in Error State + /// true to show, false to hide artifact + /// true if successful, false otherwise + public bool HideShowArtifact(ArtifactItem artifactItem, bool bShow) + { + if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity) + { + // Step One - Create the ShowNHider Obj + IShowNHide ShowHider = WorkspaceTypeHelpers.CreateShowNHiderObj(artifactItem); + if (ShowHider == null) + return false; + + // Step Two - Query if Hiding or Showing is available for this Artifact + FuncDepBoolType retVal = FuncDepBoolType.Failed; + if (bShow) + retVal = ShowHider.IQueryShow(artifactItem.Location); + else + retVal = ShowHider.IQueryHide(artifactItem.Location); + + // Step Three - Show or Hide it if supported + if (retVal == FuncDepBoolType.Success) + { + if(bShow) + retVal = ShowHider.IShow(artifactItem.Location); + else + retVal = ShowHider.IHide(artifactItem.Location); + } + else + { + // * Log error or something and return otherwise * To Do + return false; + } + + return (retVal == FuncDepBoolType.Success); + } + return false; + } + + /// // ToDo: - + /// Launches a Workspace. When for some reason an artifact location + /// is not available to launch we keep track of it and display it to the + /// user - however, we don't stop. we try to launch as many artifacts as + /// we can. + /// --------------------------------------------------------------------- + /// There are a few steps we have to do in order to successfully launch: + /// 1) Make sure all files that have the same file name are not launched together + /// 2) we must wait a little after each file to make sure that they can be resolved + /// + /// + /// Name of Workspace to launch artifacts for + /// true if 1 or more artifacts were launched, false otherwise + public bool LaunchWorkspace(string WorkspaceName) + { + // Step One - First Get all the Artifacts by Name + ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Descending); + if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts)) + { + + // Let's get the optimal Indexes for all the file artifacts + int[] optimalIndexes; + HelperFunc.IndexOptimizationQuality quality; + quality = HelperFunc.OptimalLaunchIndexesForFileArtifacts(artifacts, out optimalIndexes); + + //// + // Launch the file Artifacts according to their optimal indexes + //// + foreach (int optIndex in optimalIndexes) + { + // Launch file artifact + LaunchArtifact(artifacts[optIndex]); + + // depending on the quality of indexes sleep accordingly + int nSleepTime = HelperFunc.GetSleepTimeForQuality(quality); + + // Sleep Now before launching again + System.Threading.Thread.Sleep(nSleepTime); + } + + //// + // Launch the url Artifacts according to their optimal indexes + //// + foreach (ArtifactItem artifact in artifacts) + { + if (artifact.IsUrl) + { + LaunchArtifact(artifact); + System.Threading.Thread.Sleep(HelperFunc.DEFAULT_LAUNCH_SLEEP_TIME); + } + } + + // Signal the Workspace as Launched + Data.Workspace.WorkspaceWasLaunched(WorkspaceName); + + // Set it to this Workspace 'State' + Data.State.SetCurrentWorkspaceName(WorkspaceName); + } + return false; + } + + /// + /// + /// + /// Name of Workspace to close artifacts for + /// + public bool CloseWorkspace(string WorkspaceName) + { + ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Ascending); + if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts)) + { + foreach (ArtifactItem artifact in artifacts) + { + CloseArtifact(artifact); + + // Sleep a little + System.Threading.Thread.Sleep(HelperFunc.DEFAULT_CLOSE_SLEEP_TIME); + } + + // Clear Workspace 'State' + Data.State.ClearCurrentWorkspaceName(); + } + return false; + } + + /// + /// + /// + /// + /// true to show, false to hide artifact + /// + public bool HideShowWorkspace(string WorkspaceName, bool bShow) + { + ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Ascending); + + if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts)) + { + foreach (ArtifactItem artifact in artifacts) + { + HideShowArtifact(artifact, bShow); + + // Sleep a little + System.Threading.Thread.Sleep(HelperFunc.DEFAULT_SHOWNHIDE_SLEEP_TIME); + } + } + return false; + } + + #endregion + } +} diff --git a/WorkspaceMgr/WorkspaceMgr.csproj b/WorkspaceMgr/WorkspaceMgr.csproj new file mode 100644 index 0000000..1d6c631 --- /dev/null +++ b/WorkspaceMgr/WorkspaceMgr.csproj @@ -0,0 +1,134 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35} + Library + Properties + Foo.WorkspaceMgr + WorkspaceMgr + v3.5 + 512 + true + MyKeyFile.SNK + + + true + full + false + ..\Target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\Target\Release\ + TRACE + prompt + 4 + + + + False + False + + + False + False + + + False + False + + + False + False + + + False + False + + + False + False + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618} + DataAccessLayer + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + {48D75C4F-2749-48BB-9386-721E0E94C144} + Settings + + + + + + + + {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52} + 2 + 3 + 0 + primary + False + + + + + + + + + \ No newline at end of file diff --git a/WorkspaceMgr/WorkspaceState.cs b/WorkspaceMgr/WorkspaceState.cs new file mode 100644 index 0000000..c080442 --- /dev/null +++ b/WorkspaceMgr/WorkspaceState.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Foo.WorkspaceMgr +{ + static class WorkspaceState + { + static public List Launched_ExcelInstances = new List(); + static public List Launched_PowerPointInstances = new List(); + + static WorkspaceState() + { + } + + } +} diff --git a/WorkspaceMgr/WorkspaceTypes.cs b/WorkspaceMgr/WorkspaceTypes.cs new file mode 100644 index 0000000..2c08076 --- /dev/null +++ b/WorkspaceMgr/WorkspaceTypes.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Settings; +using Foo.Platform.Win32; +using Foo.DataAccessLayer.DataTypes; +using Foo.WorkspaceMgr.Hiders; +using Foo.WorkspaceMgr.Closers; +using Foo.WorkspaceMgr.Launchers; + +namespace Foo.WorkspaceMgr +{ + /// + /// Allows us to extend functionallity by creating our own + /// Custom Types to be used in certain scenarios + /// + internal enum CustomStateChangingTypes + { + LaunchGenericUrl + } + + /// + /// Useful for StateChanger Returns where we + /// need more information on failures + /// + public enum FuncDepBoolType + { + Success, + Failed, + ParametersInvalid, + ArtifactLocationUnavailable, + FunctionallityNotSupported, + ErrorThrown + } + + /// + /// Use this to request the proper state + /// Changing Object + /// + public enum StateChangerReqType + { + Launcher, + ShowNHider, + Closer + } + + /// + /// Class for useful Workspace Type Helpers + /// + internal static class WorkspaceTypeHelpers + { + private static configuration _configuration = null; + + static WorkspaceTypeHelpers() + { + OoganizerSettingsAcc accessor = new OoganizerSettingsAcc(); + _configuration = accessor.ReadConfigXMLFile(); + } + + #region Internal Object Creator Functions (Call these in this assembly) + + /// + /// Creates a Launcher Object from an artifact Item + /// + /// valid artifact to create a launcher for + /// object or null + internal static ILaunch CreateLauncherObj(ArtifactItem artifactItem) + { + if (artifactItem.IsUrl) + { + return CreateLauncherObj(CustomStateChangingTypes.LaunchGenericUrl.ToString()); + } + else if (artifactItem.IsFile) + { + string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location); + if (!String.IsNullOrEmpty(strRegisteredProcessExe)) + return CreateLauncherObj(strRegisteredProcessExe); + //return CreateLauncherObj(LauncherGenericType.LaunchGenericFile); + } + return null; + } + + /// + /// Creates a Hider Object from an artifact Item + /// + /// name for process to create object for + /// object or null + internal static IShowNHide CreateShowNHiderObj(ArtifactItem artifactItem) // TO DO: We can check the RAT which Process the artifact was launched in!! + { + if (artifactItem.IsUrl) + { + // To Do: Query the RAT for the process this artifact is in, then call + // the object creator function for the correct process + return null; + } + else if (artifactItem.IsFile) + { + string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location); + if (!String.IsNullOrEmpty(strRegisteredProcessExe)) + return CreateShowNHiderObj(strRegisteredProcessExe); + } + return null; + } + + /// + /// Creates a Closer Object from an artifact Item + /// + /// valid artifact to a closer for + /// object or null + internal static IClose CreateCloserObj(ArtifactItem artifactItem) // TO DO: We can check the RAT which Process the artifact was launched in!! + { + if (artifactItem.IsUrl) + { + // To Do: Query the RAT for the process this artifact is in, then call + // the object creator function for the correct process + return null; + } + else if (artifactItem.IsFile) + { + string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location); + if (!String.IsNullOrEmpty(strRegisteredProcessExe)) + return CreateCloserObj(strRegisteredProcessExe); + } + return null; + } + + #endregion + + #region Private Object Creator Helper Functions + + /// + /// Creates a Closer Object + /// + /// name for process to create object for + /// object or null + private static IClose CreateCloserObj(string ProcessNameOrCustomType) + { + object o = CreateStateChangerObject(StateChangerReqType.Closer, ProcessNameOrCustomType); + if (IsObjectOfType(StateChangerReqType.Closer, o)) + return (o as IClose); + else + return null; + } + + /// + /// Creates a Hider Object + /// + /// name for process to create object for + /// object or null + private static IShowNHide CreateShowNHiderObj(string ProcessNameOrCustomType) + { + object o = CreateStateChangerObject(StateChangerReqType.ShowNHider, ProcessNameOrCustomType); + if (IsObjectOfType(StateChangerReqType.ShowNHider, o)) + return (o as IShowNHide); + else + return null; + } + + /// + /// Creates a Launcher Object + /// + /// type of Launcher you want to create + /// object or null + private static ILaunch CreateLauncherObj(string ProcessNameOrCustomType) + { + object o = CreateStateChangerObject(StateChangerReqType.Launcher, ProcessNameOrCustomType); + if (IsObjectOfType(StateChangerReqType.Launcher, o)) + return (o as ILaunch); + else + return null; + } + + /// + /// Useful for quick Interface Type checking of StateChangers + /// + /// A StateChangerRequestTyp + /// a stateChanger Object + /// true if object is of that Type + private static bool IsObjectOfType(StateChangerReqType reqType, object o) + { + if (o != null) + { + switch (reqType) + { + case StateChangerReqType.Launcher: + return (o is ILaunch); + + case StateChangerReqType.ShowNHider: + return (o is IShowNHide); + + case StateChangerReqType.Closer: + return (o is IClose); + } + } + return false; + } + + #endregion + + #region Main Object Factory Function (All calls ultimately end up here) + + /// + /// Function is responsible for create the StateChanging Objects that we + /// need for the system. It will either be hardcoded in or be reading from + /// the settings file to know what object to create + /// + /// A StateChangerRequestType + /// the name of the process to create it for + /// an object of the correct type, the caller must then cast it + private static object CreateStateChangerObject(StateChangerReqType reqType, string ProcessNameOrCustomType) + { + if (!String.IsNullOrEmpty(ProcessNameOrCustomType)) + { + //// + // First Step - Create any Custom Types + //// + switch (ProcessNameOrCustomType) + { + case "LaunchGenericUrl": + { + if (reqType == StateChangerReqType.Launcher) + return new Launchers.Launcher_Web(); + } + break; + } + + //// + // Second Step - Read thru the Configuration and create the corresponding + // object as the Configuration says we should use + //// + foreach (ButtonHookSettings.ProcessName processObj in _configuration.ButtonHook.AllowedProcessNames.ProcessNames) + { + + if (processObj.ProcessExe == ProcessNameOrCustomType.ToUpper()) + { + switch (reqType) + { + case StateChangerReqType.Launcher: + switch (processObj.Launcher.ToUpper()) + { + case "WEB": + return new Launcher_Web(); + + case "SHELL": + return new Launcher_Shell(); + + case "EXCEL": + return new Launcher_Excel(); + + case "VISIO": + return new Launcher_Visio(); + + default: + return new Launcher_Generic(); + } + + case StateChangerReqType.Closer: + switch (processObj.Closer.ToUpper()) + { + case "IE": + return new Closer_IE(); + + case "OFFICE": + return new Closer_Office(); + + default: + return new Closer_Generic(); + } + + case StateChangerReqType.ShowNHider: + switch (processObj.ShowHider.ToUpper()) + { + case "OFFICE": + return new ShowNHide_Office(); + + default: + return new ShowNHide_Generic(); + } + + } + } + } + } + return null; + } + + #endregion + } +} diff --git a/zEasyTest/Program.cs b/zEasyTest/Program.cs new file mode 100644 index 0000000..22ddfc9 --- /dev/null +++ b/zEasyTest/Program.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.Platform; +using Foo.Platform.Win32; +using Foo.Settings; +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; + + +namespace zEasyTest +{ + class Program + { + static void Main(string[] args) + { + foreach (Win32Functions.RunningObject running in Win32Functions.GetRunningObjects()) + { + if (running.name == "Doris") + { + int j = 5; + j = j + 5; + } + } + + + + + // DataAccessLayer + //DB.DeleteDefaultDB(); + //DataAccessLayer.TestData.TestData.FillDBWithTestData(); + + // Settings + //Settings_Test.MockAroundWithSettings(); + + // WorkspaceMgr + //WorkspaceMgr_Test.TestSingleArtifactLaunch(); + //WorkspaceMgr_Test.TestWorkspaceLaunch(); + //WorkspaceMgr_Test.TestConfiguration(); + + int i = 5; + i = i - 5; + } + } +} diff --git a/zEasyTest/Properties/AssemblyInfo.cs b/zEasyTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2d03398 --- /dev/null +++ b/zEasyTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("zEasyTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("zEasyTest")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9543b631-51de-4051-b115-ac39fd28e0cc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/zEasyTest/Settings_Test.cs b/zEasyTest/Settings_Test.cs new file mode 100644 index 0000000..a2f01c4 --- /dev/null +++ b/zEasyTest/Settings_Test.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Foo.Settings; + +namespace zEasyTest +{ + static class Settings_Test + { + + public static void MockAroundWithSettings() + { + OoganizerSettingsAcc acc = new OoganizerSettingsAcc(); + + configuration conf = new configuration(); + conf.ButtonHook.AllowedProcessNames.AddProcessName(new ButtonHookSettings.ProcessName("Doris", "Doris1", "Doris3", "Doris4", "123", "dd", "vv", 0, 0)); + conf.ButtonHook.AllowedProcessNames.AddProcessName(new ButtonHookSettings.ProcessName("Voris", "Voris1", "Voris3", "Voris4", "123", "dd", "vv", 0, 0)); + conf.ButtonHook.AllowedProcessNames.AddProcessName(new ButtonHookSettings.ProcessName("Koris", "Koris1", "Koris3", "Koris4", "123", "dd", "vv", 0, 0)); + + //configuration config = acc.ReadConfigXMLFile(); + + //configuration config = acc.ReadConfigXMLFile(@"D:\Users\HPinvent\_ROOT_\TestANizer\DataAccessLayer\Doris.xml", false); + + acc.WriteConfigXMLFile(@"D:\Users\HPinvent\_ROOT_\TestANizer\DataAccessLayer\Doris.xml", conf); + + //acc.WriteBlankConfigXMLFile(@"D:\Users\HPinvent\_ROOT_\TestANizer\DataAccessLayer\Doris.xml"); + } + + + } +} diff --git a/zEasyTest/WorkspaceMgr_Test.cs b/zEasyTest/WorkspaceMgr_Test.cs new file mode 100644 index 0000000..85a7049 --- /dev/null +++ b/zEasyTest/WorkspaceMgr_Test.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Foo.DataAccessLayer; +using Foo.DataAccessLayer.DataTypes; +using Foo.Platform; +using Foo.GUILib; +using Foo.WorkspaceMgr; + +namespace zEasyTest +{ + static class WorkspaceMgr_Test + { + + static public void TestConfiguration() + { + Configurations.Configure_Excel2007(); + } + + static public void TestSingleArtifactLaunch() + { + //WorkspaceMgr mgr = new WorkspaceMgr(); + //mgr.LaunchArtifact(DataTypeHelpers.CreateLocationOnlyArtifact(@"D:\Users\HPinvent\Documents\KeepFocusedTask.txt")); + //mgr.LaunchArtifact(DataTypeHelpers.CreateLocationOnlyArtifact(@"http://www.google.com/")); + } + + static public void TestWorkspaceLaunch() + { + WorkspaceMgr mgr = new WorkspaceMgr(); + + string strTestWorkspace = "Presentations"; + + mgr.LaunchWorkspace(strTestWorkspace); + + System.Threading.Thread.Sleep(30000); + + mgr.CloseWorkspace(strTestWorkspace); + + + //mgr.LaunchArtifact(DataTypeHelpers.CreateLocationOnlyArtifact(@"D:\Users\HPinvent\Documents\KeepFocusedTask.txt")); + } + + } +} diff --git a/zEasyTest/zEasyTest.csproj b/zEasyTest/zEasyTest.csproj new file mode 100644 index 0000000..469b304 --- /dev/null +++ b/zEasyTest/zEasyTest.csproj @@ -0,0 +1,83 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {6CDF553C-5060-4871-9CE8-63F66346716A} + Exe + Properties + zEasyTest + zEasyTest + v3.5 + 512 + + + true + full + false + ..\target\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\target\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + {C7E4B4C1-64D4-45FF-AAFD-C4B9AE216618} + DataAccessLayer + + + {C1282050-455B-44F4-8520-1C005E38EFB2} + GUILib + + + {F6929AFC-BF61-43A0-BABD-F807B65FFFA1} + Platform + + + {48D75C4F-2749-48BB-9386-721E0E94C144} + Settings + + + {09ED5DCC-9350-42E5-8E3A-4A3EA25BCD35} + WorkspaceMgr + + + + + \ No newline at end of file