pNJFCSh5plR
zkOrW?C9AwalEnL&@5kS}?ar?bbwB<2H*Z(Ge#ZkhUHZK^y5{}+?)}HAT*K*$T_@lD
zYQm4*sps!J@r>jh1K;}df)xGMqVs;feEYov?l{MF@VjMy_1erEw(q&5?9t5@6lT0h08aUayl)T^=Xl!}Vl#Gu+=`FzIxjl|*#umwA?YPBGeOkZk(7
zLNcZ3Ferv{+N)DoOg2Je82Hw#XxGa>kZxAWc0ZA`J5H2oA%4IZ$l+c^V|cZ2Ck`a#UzY
z*PA^?_#BKH?UNY8@JUHbzVyVC8}Gl=_Q)jjq*?xp6899|pL_7~%}?e&F**J9;RU0A
zGu}J1_0112C?4f6e)V6o;s#rVybL$7UHa)0@k
zN3J|^Y@}1X(!WZQ^En}^jwlAfRica{kP&&2wsz=N6E*&zu?1S&lIr{6m
ztit!bOLRXzubZ;uxf6b#_O}gpfAG!^D{E42eKYRpDdd14zqv!ubgEK&%gOd{MSFfRlcgmv%#=pFJAQ^Hh?k}t__QI=+T2-C;VGlCI_G4qh)au>bJ|zn
z>k}82UoH5(99J2B>jB?FD4!3|ArHw4cS81zVh*821%(K{S_mx!+7m+m$7B4zi=&sH
zoh6d*%H8{_`I)zxw$ELjb^4DV&baU0Mb!v^_dR}c`rMzck566Q^vK)eZW}Xr&O1B5
z|7_XF8rxHs@3XXR-}BCr_?jEyx9z&`tE2*HIW_m_Hxs(tw+}VsUUAk>!JIvoc4#4yq7M^X!|;4
z{ks=@;@!OFxu*2H>}v*HapyDhXVf0NxA4u~3DZlSz5J5%U#Y$M%2UoMUijLV+gEs9
z*5^E{huN!Foc+g#*EMY@_}cfvUyr_V;XTENw&Vm(3oco{@tW`AcAWaef_Y-*{?~rK
zasA;jZ#h4naLdLwra$Q1^i=w_U!FYSy{q5V;^^6kqi1=>XaNIpV5nzs{}HCJCo*{)
z6u+DlZ8=2zCQHK8Of;9?=c)I2V}t9wo`{6ts)f4Mt5=gm^3q6rb!&>qvL|EE@i-~O
zdZ@N+{V2~!&+uJCcMaZ@twq9u9zDmj)q9Kb8jCrM(mDb&0!`=IjDY8ck+~se0+EcK
zQN(W7BS7Df<;f@*0-ee`T_)@#0-pL*}B
zN51t~zAu~jPx-E*f}&oLf`hB`oIzRsJ>!4c_1Fz}otf#aJ$CJuQ{!%G&svi*^u1rd
z8l;;)@n5H3`ke3No40yiEkD`&Zd>4;!G@>uLl0LTd1d>trO&^3s_y;GJEw-T-uh|6
z1$*9n>5<|wMT>5^WWg)@s!!PPY3Ih|U)*=^o$-CCv&0hWeV=tDyexz#8)cY^kcvr)BFDDHy*pTp>
zXG6ljWJ&ULZ~q@(Gxoo#jap^z>b}C07Fp+7bOmuy6RF;l5rx?b5xp4*X
zw%voeQdM`RQGy{t-wCXuVdBDI)t1v1eZdgD>(;W(l_!;6yz0su4_8h3x}de}j$I9J
z{&nfa&(`04;<}El-ewxG;U^z6nd#JZRiKxNYg4
zNB{A}$o2OZ4*TNoN6s8~#Zx=qzV4kT>(5EQ+o&5ZUol|$8uw54zb=_Y*uMQpb_yw8s4`!rJ+xN=Wk>@;qR##=k0q2Y>wj@|C
z?D}QbpT~}=`MS71F0J!#H=FDI_ka4z++ivI?0Wi&@28!6zdbbM>&p&Qow$Ce6#vGH
z=X_xaES~(<)~gP-Cw=dGr2ABJ?rBvQrSR}IgN
zxA_h`Px7t0=!7AKEwgnW<}7;nE8QidpVgnZcbT_pQHlM-(|+9AzGe2xm&Rn=wR=O{
zZqJ6eYa@2o>7;@UaTkKNIbvPfR>iFasRNG&`);ec-!t0OZH*-n8>{XY_1!Ocx}Sr`
z8ZErx+Epm)`q@(5b3<8cL&_I>os)`2Y+Ra{bmH*ZP49l=zBbN%-jrcipV=rU1>SG+
zzWdSPtQ*p|Shj*v+?I@{ULyKo46yg@r|hg}6^VdDqe#PVp>`T2s`{(3TEXXY!2d
z*)HWrplD^`niKZ9s=^Hg2$xC}i_Wa8Ep@HLdZ83Q42X|-8fc0y+_k~{XRL1aU}LvU
zS>ZVBgN;W99BBIX>VJN6O6rRjxun(6u0>nBQ=-(FR#A|KohD+Y)tMNjN^3`6$XieV
zH|B8aj>@XTj|Ae-3O^Fq+UP1Pg&yh-jucY2ZN-ISd)6G|J>w$if1@q_?XK*B=Po(l
z{r30U{xTEA|`Ke=J?jW0ADc0>)&11`)h@@IcV2mI
z{WEKpE#8wqp3+yCd7+b
zlkBUne_^Q9wR7M01xu&zKmYAlZ?$eb=bp`{yis_dbX{sq-3zz9GVfH!Yr}Rf_&)BU
z_a3`sYv&uKo1eaZ*C*S4d9Lx=bBhj~UKr9=6OFJ`eV?sZ6?z&A11vo~rIDc_WqHPW
z3bpwc%YqRU@MzCP5wDSdzl?tDg_j0FA3n76;}f~gG0}UzWD-1_Rw2>bJhNvy(X;ha
zJySd3%c1{H9_xm|{28TXbV+Oe217tjF;}P2R%BLS8W}($vGUsLC_TGgHGo@}|k!
za)S;seZ8gDLUyqjkI;p%IL4fR}o(a3Yh
z{8PX9K-+m!rq5gb%+(dIUi8=lgHtQt&Oi6JOY&DAooYS0Yw!~1?2k9*xX<0cWZ*;2
z+dg#6fBNT&tje?lx3&)${P{O?e;J!=D>PW{`8e5s$HDwFKlmkY=Hr823l~e1{^}`f
zYg{|wt%vPTE%;Z#%!f}oGT5=={f^DsvMVRNzNos>a{iuo0`i-8eEiPl^;HM=dfG}(
zd$;1@+K!74oir_Z@Jk=Rx@gDi^L2&YMf6Fo(R6P3Nu$^X4E@!xH8ZoPWz)3@2@4wwFT*^Uoqzx|~7$LT{4Ry=#@
z<)_>>=w@}U<`
zIg(YrdFwIT;lYcXUsvyYw$YYx&%H;+c5J)uFQ%69&+eKrLLPX-#oP9D?tJTS3$M*N
zW60Y{ZyhmZtr;?I)#}c>?mBwb)|wCQHy8Z+<=;;_eZ`icM|2Y}D)0Pbhi>7{JI0u&
zA9{7mqd#m7AK2IApW9)-V8GI0r=-)z8ko<=u^QoU{LY=z@oSe$QWZ-rufS=Na+K+C`5nel#g~N%z7BI-Y;K%i7gy
zQ36x<=br9QV#5*^`2Fo+c#ps<`F@Ap3?-8NKXWj!Gq7P}0TyZuWENs(kP=GYK-WNf
zf#w4BHdX8;R92EY+-tI}_8o>TnPLFv5Zx!cdmr!L>U>GU_rwz>09T$#bTsW9KKblpeWlq~BwKeuIC
zu^f{=F8(ZAvOkGexhF=;V(O&>SI?gBxFxT#bys6%iq_U;i>?;0zvFhBW!=Q-uwr(qM*7GS}!0o0W!q-l0!!qG%R?k6-ciWo@2+nB(P0xwE464+CK
zx9(XD`N2ceh&CTa+kaV*Qm
z(R$xWr*3%HuZv&yBF<DP*$>-wC;Dy
z+J%q3)F*pMY_Z=S^Yfj|_DNpRURBB$qh|!)cptf|*JJ*&Z4UaIjgQN5WD6c&qZycA
WXuY`V*1o3G2h(o3-#iGuMGgSm^?TX?
literal 0
HcmV?d00001
diff --git a/DotNet.Revit.Ribbon/App.config b/DotNet.Revit.Ribbon/App.config
new file mode 100644
index 0000000..4bfa005
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/App.xaml b/DotNet.Revit.Ribbon/App.xaml
new file mode 100644
index 0000000..90411b5
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/App.xaml.cs b/DotNet.Revit.Ribbon/App.xaml.cs
new file mode 100644
index 0000000..9049f9e
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace DotNet.Revit.Ribbon
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj b/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj
new file mode 100644
index 0000000..c081775
--- /dev/null
+++ b/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj
@@ -0,0 +1,119 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}
+ WinExe
+ Properties
+ DotNet.Revit.Ribbon
+ DotNet.Revit.Ribbon
+ v4.8
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\AdWindows.dll
+
+
+ D:\Program Files\Autodesk\Revit 2016\ManagedMC3.dll
+
+
+ False
+ D:\Program Files\Autodesk\Revit 2016\Microsoft.Expression.Interactions.dll
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.Ribbon/MainWindow.xaml b/DotNet.Revit.Ribbon/MainWindow.xaml
new file mode 100644
index 0000000..687853d
--- /dev/null
+++ b/DotNet.Revit.Ribbon/MainWindow.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/MainWindow.xaml.cs b/DotNet.Revit.Ribbon/MainWindow.xaml.cs
new file mode 100644
index 0000000..7f04051
--- /dev/null
+++ b/DotNet.Revit.Ribbon/MainWindow.xaml.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using RS = DotNet.Revit.Ribbon.Properties.Resources;
+
+namespace DotNet.Revit.Ribbon
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ [DllImport("gdi32.dll")]
+ private static extern bool DeleteObject(IntPtr hObject);
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ // 设置大图标
+ this.ID_DoNet.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_Revit.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_GitHub.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_GitHubChild.LargeImage = this.ConvertTo(RS.Github32);
+
+ // 绑定命令
+ this.ID_DoNet.CommandHandler = new CmdCommand();
+ this.ID_Revit.CommandHandler = new CmdCommand();
+ this.ID_GitHub.CommandHandler = new CmdCommand();
+ this.ID_GitHubChild.CommandHandler = new CmdCommand();
+ }
+
+ private BitmapSource ConvertTo(Icon icon)
+ {
+ var hIcon = icon.Handle;
+ try
+ {
+ var source = Imaging.CreateBitmapSourceFromHIcon(
+ hIcon,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+ return source;
+ }
+ finally
+ {
+ DeleteObject(hIcon);
+ }
+ }
+ }
+
+ public class CmdCommand : ICommand
+ {
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ var item = parameter as Autodesk.Windows.RibbonItem;
+ MessageBox.Show(string.Format("This is {0} command test !!", item.Text));
+ }
+ }
+}
diff --git a/DotNet.Revit.Ribbon/Properties/AssemblyInfo.cs b/DotNet.Revit.Ribbon/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3adf0bb
--- /dev/null
+++ b/DotNet.Revit.Ribbon/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("DotNet.Revit.Ribbon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.Ribbon")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[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/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs b/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..9d2781e
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.Ribbon.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.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() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [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("DotNet.Revit.Ribbon.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
+ ///
+ internal static System.Drawing.Icon Github32 {
+ get {
+ object obj = ResourceManager.GetObject("Github32", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.Ribbon/Properties/Resources.resx b/DotNet.Revit.Ribbon/Properties/Resources.resx
new file mode 100644
index 0000000..24d3004
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Resources.resx
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnksoAZ5LKAGeSygBnksoAZpDIAGyY0gltmdIcbJjRMGqW
+ zz9plc1LaZXNS2qWz0BsmNEwbZnTHGyY0gllkMgAZ5LKAGeSygBnksoAZ5LKAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBnksoAapbPAWuX0RhplM1AYYrAalZ9
+ sY1NcqSoSWyduUdqmsFHaprCSWyduU1ypKhVfLCOYIrAammUzUFrl9AZapbOAmeSygBnksoAZ5LKAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBnksoAaZTNAGuWzxNok8tJWYG2hkhs
+ nbxBZJPiQ2aV9ktwof5Qdqn/Unis/1F2qf9Qdaf/THCh/kVol/ZCZJPiSGydvFmBtoZok8tKa5bPFGmU
+ zQBnksoAZ5LKAGeSygAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAZ5LKAGiTywFqls8rX4i+dEhs
+ nbxCZJPuTXKk/1Z+tP9chLr/Z5LL/2aSzP9kj8r/YozF/2aQyP9nksr/ZY/G/1yEuf9NcqX/Q2WU70hs
+ nbxfiL51apbPLGiTywFnksoAZ5LKAGeSygAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBolMwDaZXNOld+
+ so9CZJPcSGye/1qDuv9lkMn/YIrE/16Gvf9mkcr/ZpHL/2SOyP9hi8X/ZI7F/2eSyv9nksr/aJLK/2aR
+ yf9iisD/THCi/0Jkk91XfrKQaZXNO2iUzANnksoAZ5LKAAAAAAAAAAAAAAAAAGeSygBnksoAaJPLAWmV
+ zTtUeq6ZQWOS6lN6rv9ficL/X4rD/2WQyf9ficP/XYa9/2aRyf9mkcv/Y47I/2GMxf9jjMT/Z5LK/2eS
+ yv9oksr/ZpDI/2mUzP9nkcn/VXyv/0FjkutUeq2aaZXNPGiTywJnksoAZ5LKAAAAAABnksoAZ5LKAGmU
+ zQBqls8sV36ykEFjkupZgbf/ZZDL/2CKxP9gisT/ZZDJ/2CJw/9dhr3/ZZDI/2aRy/9jjsj/YYzG/2GK
+ wv9nkcn/Z5LK/2mTyv9mkcj/aJPL/2iTyv9nksv/WIC0/0FjkutWfbGRapbOLWmVzQBnksoAZ5LKAGeS
+ ygBnkssAa5bPFF+IvnZCZJPdWIC1/2qW0P9lkMr/YIrD/2CKxP9lkMn/YIrD/12Fvf9lkMf/aZPM/2eQ
+ x/9njsT/Z47D/2uUy/9nksr/aZPK/2eRyP9ok8r/aJPK/2eSyv9ok8v/V32w/0Fjk95eh713a5bPFWeS
+ ywBnksoAZ5LKAGqWzwJnk8tLSGucvVB2qP9tm9T/aZbQ/2WQyv9gisP/YIrE/2WQyf9gisP/XIS8/1V5
+ r/9EYpj/OVWK/zhSh/9BW47/XXur/3CWyf9ok8v/aJLJ/2iSyv9ok8r/Z5LK/2iTy/9nkcj/SGyd/0dr
+ nL9nkspNapbPAmeSygBnksoAa5fQGliAtIhEZ5bwapbO/2+d1/9pltD/ZZDK/2CKw/9gi8X/ZJDJ/2CK
+ xP9Jbab/JkF4/yE7dP8kQHn/JUF6/yA6cv8jPXT/VXKi/26XzP9nksn/Z5LJ/2iTy/9nksr/aZTL/2WQ
+ yP9agrf/Q2aV8Vh/tIprl9AbZ5LKAGONxABplMxDR2ubvlV8r/9zotz/bpzW/2mWz/9lkMr/YIrE/2GL
+ xf9kkMn/X4nD/zVUjP8fOXD/PVqQ/1mAuf9Ygbv/QmSe/yA7cv80ToP/bZPG/2aQx/9kjsb/aZTL/2eS
+ yv9plMv/ZI7G/2SOxf9Rdqj/R2ubwGiUzEVfiL0AbJjSC1+Iv25DZZXlZ5PK/3Oi3f9unNb/aZbP/2WQ
+ yv9gisT/YYzF/2SQyf9gisP/NlaO/x44b/9HY5b/bpPG/2eOxf9OcKj/Ijxz/y5Jf/9njcH/aJLJ/2GL
+ wv9pk8v/aJLK/2qUy/9hi8P/Zo/G/1+HvP9CZJPmX4i+b2yZ0gxtmdIfVHuukUltnfhwn9j/c6Lc/26c
+ 1v9plc//ZZDK/2CKxP9hjMb/ZJDJ/2CKxP9Oc6z/KEV8/yQ/d/80ToP/NVCF/ydBd/8gOnH/PFyT/2eQ
+ x/9plMv/YozD/2eSyf9qlMv/aZPL/12Hvv9mkMf/ZpDH/0ZpmfhUeq6TbZnSIGuX0DRMcKKsUniq/3Oj
+ 3f9zotz/bpzW/2mVz/9lkMr/YIrE/2KNx/9lkMn/YIrD/12Gv/9Ncaj/JkF6/yA7c/8mQnr/ME6H/0Fj
+ m/9gicH/Z5LK/2mUy/9mkMf/ZZDI/2iTy/9lkMj/WoS7/2mTyv9nksr/TXKj/0twoa5rl9A1apXORkdr
+ m75Zgrb/dKPd/3Oi3P9unNb/aZbP/2WQyv9gisT/Yo3G/2SQyf9gicP/XYa//0Jkm/8gO3P/MEuC/1qA
+ t/9dh8H/X4jA/2eSyf9nksr/aJPL/2mUy/9mkcn/Z5LK/2CKwf9eiL//apTL/2iTy/9Teav/R2qbv2mV
+ zUholMxURWmZxlyFuv90o97/c6Lc/26c1v9plc//ZZDK/2CKxP9ijcf/ZZDJ/2CKw/9dhr//SW2k/yI9
+ dv8vSX//X32v/2iLv/9ji8L/ZpDI/2eSyv9oksr/a5XM/2aRyf9kj8b/XYe9/2WQyP9qlMv/aJPL/1V7
+ r/9FaJjIaJPLWGiUzFVFaJnGXIW6/3Sj3v9zotz/bpzW/2mVz/9lkMr/YIrE/2OOyP9kkMn/YIrD/1yE
+ vf9GaZ7/JUB4/yA6cv8jPHT/NE2C/2F/rv9rlcr/Z5LK/2eSyv9qlcz/Z5LJ/2GMw/9eib//Z5LK/2mU
+ y/9ok8v/VXuv/0VomMhok8tZaZXOSEdqm79agrf/dKPd/3Oi3P9unNb/aZXP/2WQyv9gisT/Y47I/2WQ
+ yf9gisT/TnOs/yVBeP8kPnf/M1KK/zBOh/8fOXL/MUt+/22Qwf9ok8v/Z5LK/2qUy/9ok8r/Yo3E/2OO
+ xf9pk8v/aZPL/2iTy/9Ueaz/R2qawGmVzUprl9A2S3ChrlN5rP90o93/c6Lc/26c1v9plc//ZZDK/2CK
+ xP9jjsj/ZZDJ/2GLxP89Xpb/Hzlx/zlUiv9kjMT/XIW//y1Kgv8hOnH/W3qs/2qUzP9nksr/aZPL/2mU
+ y/9mkcn/Z5LK/2qUy/9ok8r/Z5PL/05ypP9Lb6Gwa5fQN22Z0iFTea2USm6f+XGf2f9zotz/bpzW/2mV
+ z/9lkMr/YIvE/2SPyf9lkMn/YYvE/zpbk/8eOXD/PlqO/2+Vyv9gisP/L02F/yA6cf9Wdaf/bJbN/2eS
+ yv9ok8r/apTL/2eSyv9nksr/apTL/2eSyv9mkMf/R2qa+VN5rJZtmdIibJnSDV6HvXFDZpXnaZXM/3Oi
+ 3P9unNb/aZXP/2WQyv9hi8T/ZI/J/2WQyf9hi8X/SGyl/yE7c/8oQnn/T2ud/0Zkmf8kPnb/ITty/ztW
+ iv9tkcT/Z5LL/2eSyv9qlcv/Z5LK/2mTy/9plMv/Z5LL/1+Ivf9CZJPoXoe9c2yZ0g2Bs/EAaJPLSEZq
+ msNXf7P/c6Ld/26c1v9plc//ZZDK/2GLxP9kj8n/ZZDK/2CKxP9bg7r/PmCY/yI+d/8fOXH/Hzlx/yM+
+ df8lQXn/KUR7/2aKvf9ok8v/Z5LK/2mUy/9qlMv/apTL/2eSyv9nksv/UXap/0ZpmsRok8tJc6HcAGeS
+ ygBrl9AeVn2xjkVpmPNsmdH/b53X/2mVz/9lkMr/YYvF/2SPyf9lkMn/YIrE/12Gvf9kj8f/Unmz/0Fk
+ nv9CZZ7/UHWs/1qCuf9Rdq7/ZIzD/2eSy/9nksr/aJLK/2qUy/9ok8r/Z5LL/2KLwf9DZZTzVn2xkGuX
+ 0B9nksoAZ5LKAGqWzwNnkclSRmmaxFR6rf9unNb/aZXP/2WQyv9hi8X/ZJDK/2WQyf9gisP/XYa9/2aS
+ yv9nk8z/ZZDK/2ONx/9jjcP/aJPL/2iTy/9nksr/Z5LK/2eSyv9nksr/Z5LK/2eSyv9nksr/TnOl/0Zp
+ mcVmkclTapbPA2eSygBnksoAZ5PLAGuXzxhchbp9QmSU41yFu/9qltD/ZZDK/2GLxf9kkMn/ZZDJ/2CK
+ w/9ehr3/Z5LL/2aRy/9kj8j/YozE/2SNxP9nksr/Z5LK/2eSyv9nksr/Z5LK/2eSyv9nksr/aJPL/1h/
+ s/9BY5LkXIS6f2uXzxlnk8sAZ5LKAGeSygBnksoAapXOAGqVzjNUeq6YQmWU71yFvP9mkcv/YYvF/2WQ
+ yv9lkMn/YIrD/16Hvf9nk8z/ZpHL/2SPyf9hi8P/ZY/G/2eSyv9nksr/Z5LK/2eSyv9nksr/Z5LK/2iT
+ y/9bg7j/QmST8FN6rZlqlc40apbOAGeSygBnksoAAAAAAGeSygBnksoAaZTMA2iUzENRdqmiQmSU8Fd+
+ tP9hi8X/ZZHL/2WQyf9gisP/X4i+/2eTzP9mkcv/ZI/J/2GLwv9mkcj/Z5LK/2eSyv9nksr/Z5LK/2eS
+ y/9nksr/WH+0/0Jkk/BQdqmiaJTMRGmUzANnksoAZ5LKAAAAAAAAAAAAAAAAAGeSygBnkssAaZTNBWiU
+ zENTeq2ZQWOS5ExwpP9hi8P/ZZDK/2CKxP9fiL7/aJPN/2aRy/9kj8j/YozC/2eRyf9nksr/Z5LK/2eT
+ y/9ok8v/YozD/090pv9BY5LlU3qtmmiUzERplc0FZ5PLAGeSygAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeS
+ ygBnk8sAaZTMA2qVzjRchLp/RmmZxkNmlvRQdqn/WYG4/1+Ivv9olM7/ZpLM/2SPyf9jjML/aJPL/2iT
+ y/9mkcj/YIm//1J4q/9DZpX1RWiZx1yEuYBqlc41aZTMBGeTywBnksoAZ5LKAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAZ5LKAGeSygBnksoAapbPAGuWzxpmkclUVXywkkZpmcdBY5LqRmmY+k91p/9Teq7/Vnyx/1V6
+ rP9Ve67/T3Sm/0hrm/pCZJPqRWmZx1V8sJNmkchVa5bPG2uX0ABnksoAZ5LKAGeSygAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAaJPLAGqWzwRrl9AgZ5LKTF2Gu3ZSeKuaSm6ftEZp
+ mcVFZ5fMRGeXzUZpmcVKbp+1UXeqml2Fu3dnkspMa5fQIWqWzwRok8sAZ5LKAGeSygAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAZ5LKAGeSygBumtQBbJnSD2yZ
+ 0iVrls88aJTMU2eSymNnkspjaJTMU2uWzzxsmdImbJnSD22a0wFnksoAZ5LKAGeSygBnksoAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/AAAP/gAAB/gAAAHwAAAA8AAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACAAAABwAAAA8AAAAPgAAAH+AAAH/wAAD8=
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs b/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..ff2479a
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.Ribbon.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.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/DotNet.Revit.Ribbon/Properties/Settings.settings b/DotNet.Revit.Ribbon/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ShortKey/CmdShortKey.cs b/DotNet.Revit.ShortKey/CmdShortKey.cs
new file mode 100644
index 0000000..81b6521
--- /dev/null
+++ b/DotNet.Revit.ShortKey/CmdShortKey.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Attributes;
+using Autodesk.Windows;
+using System.Reflection;
+
+namespace DotNet.Revit.ShortKey
+{
+ ///
+ /// 动态设置命令控件的快捷键
+ ///
+ ///
+ [Transaction(TransactionMode.Manual)]
+ public class CmdShortKey : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
+ {
+ // 基于Revit的命令控件动态设置快捷键测试....
+
+ var panel = commandData.Application.CreateRibbonPanel("ShortKeyTest");
+ var data = new PushButtonData("ID_BIMAPI", "ShortKey", typeof(CmdTest).Assembly.Location, typeof(CmdTest).FullName);
+ var btn = panel.AddItem(data) as Autodesk.Revit.UI.RibbonButton;
+
+ btn.SetShortCut("BIMAPI");
+
+
+ // 修改 门 按钮的快捷键
+
+ var item = Autodesk.Windows.ComponentManager.Ribbon.FindItem("ID_OBJECTS_DOOR", false);
+ if (item == null)
+ return Result.Succeeded;
+
+ item.SetShortCut("DOOR");
+ return Result.Succeeded;
+ }
+ }
+
+ [Transaction(TransactionMode.Manual)]
+ public class CmdTest : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ System.Windows.MessageBox.Show("Shortcut is valid!!");
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj b/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj
new file mode 100644
index 0000000..ff43bf1
--- /dev/null
+++ b/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}
+ Library
+ Properties
+ DotNet.Revit.ShortKey
+ DotNet.Revit.ShortKey
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\AdWindows.dll
+ False
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFramework.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFrameworkServices.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ShortKey/Properties/AssemblyInfo.cs b/DotNet.Revit.ShortKey/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..590ff4f
--- /dev/null
+++ b/DotNet.Revit.ShortKey/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("DotNet.Revit.ShortKey")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.ShortKey")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[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("d36eef7d-e6e8-454d-8bcd-b33459a6c9cd")]
+
+// 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/DotNet.Revit.ShortKey/ShortKeyHelper.cs b/DotNet.Revit.ShortKey/ShortKeyHelper.cs
new file mode 100644
index 0000000..1ff7110
--- /dev/null
+++ b/DotNet.Revit.ShortKey/ShortKeyHelper.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UIFramework;
+using UIFrameworkServices;
+
+namespace DotNet.Revit.ShortKey
+{
+ public static class ShortKeyHelper
+ {
+ ///
+ /// 基于Revit封装的RibbonButton设置其快捷键.
+ ///
+ /// RibbonButton.
+ /// 快捷键字符串.
+ ///
+ public static bool SetShortCut(this Autodesk.Revit.UI.RibbonButton btn, string key)
+ {
+ if (btn == null)
+ return false;
+
+ var item = btn.GetType().InvokeMember("getRibbonItem",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
+ Type.DefaultBinder, btn, null);
+
+ if (item == null)
+ return false;
+
+ return (item as Autodesk.Windows.RibbonItem).SetShortCut(key);
+ }
+
+ ///
+ /// 基于通用库封装的RibbonCommandItem设置其快捷键.
+ ///
+ /// RibbonCommandItem.
+ /// 快捷键字符串.
+ ///
+ public static bool SetShortCut(this Autodesk.Windows.RibbonItem commandItem, string key)
+ {
+ if (commandItem == null || string.IsNullOrEmpty(key))
+ return false;
+
+ var parentTab = default(Autodesk.Windows.RibbonTab);
+ var parentPanel = default(Autodesk.Windows.RibbonPanel);
+
+ Autodesk.Windows.ComponentManager.Ribbon.FindItem(commandItem.Id, false, out parentPanel, out parentTab, true);
+
+ if (parentTab == null || parentPanel == null)
+ return false;
+
+ var path = string.Format("{0}>{1}", parentTab.Id, parentPanel.Source.Id);
+ var cmdId = ControlHelper.GetCommandId(commandItem);
+
+ if (string.IsNullOrEmpty(cmdId))
+ {
+ cmdId = Guid.NewGuid().ToString();
+ ControlHelper.SetCommandId(commandItem, cmdId);
+ }
+
+ var shortcutItem = new ShortcutItem(commandItem.Text, cmdId, key, path);
+ shortcutItem.ShortcutType = StType.RevitAPI;
+ KeyboardShortcutService.applyShortcutChanges(new Dictionary()
+ {
+ {
+ cmdId,shortcutItem
+ }
+ });
+ return true;
+ }
+ }
+}
diff --git a/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj b/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj
new file mode 100644
index 0000000..d7d9635
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}
+ Library
+ Properties
+ DotNet.Revit.ViewTransform
+ DotNet.Revit.ViewTransform
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ViewTransform/Properties/AssemblyInfo.cs b/DotNet.Revit.ViewTransform/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..13719ac
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/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("DotNet.Revit.ViewTransform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.ViewTransform")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[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("4f7735c6-e3bf-4dfb-8619-eab9ab4264e3")]
+
+// 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/DotNet.Revit.ViewTransform/ViewTransformHelper.cs b/DotNet.Revit.ViewTransform/ViewTransformHelper.cs
new file mode 100644
index 0000000..ce91bf2
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/ViewTransformHelper.cs
@@ -0,0 +1,54 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit.ViewTransform
+{
+ public static class ViewTransformHelper
+ {
+ ///
+ /// 屏幕点转为空间三维点.
+ ///
+ /// 指定转换到的视图.
+ /// 指定屏幕上的点.
+ ///
+ public static XYZ ScreenToWorld(this View view, System.Drawing.Point point)
+ {
+ if (view == null)
+ throw new NullReferenceException();
+
+ var uiDoc = new UIDocument(view.Document);
+ var uiView = uiDoc.GetOpenUIViews().FirstOrDefault(m => m.ViewId == view.Id);
+
+ if (uiView == null)
+ throw new NullReferenceException();
+
+ var rect = uiView.GetWindowRectangle();
+ var corners = uiView.GetZoomCorners();
+
+ var mousePoint = new XYZ(point.X, point.Y, 0);
+
+ var screenLeftlower = new XYZ(rect.Left, rect.Bottom, 0);
+ var screenRightupper = new XYZ(rect.Right, rect.Top, 0);
+
+ // 换算比例
+ var scale = corners[0].DistanceTo(corners[1])
+ / screenLeftlower.DistanceTo(screenRightupper);
+
+ var xdis = (point.X - screenLeftlower.X) * scale;
+ var ydis = (screenLeftlower.Y - point.Y) * scale;
+
+ var vp = uiDoc.ActiveView.UpDirection;
+ var vr = uiDoc.ActiveView.RightDirection;
+
+ var distance = mousePoint.DistanceTo(screenLeftlower) * scale;
+ var result = corners[0] + vr * xdis + vp * ydis;
+
+ return result;
+ }
+ }
+}
diff --git a/DotNet.Revit.sln b/DotNet.Revit.sln
new file mode 100644
index 0000000..be4cbe1
--- /dev/null
+++ b/DotNet.Revit.sln
@@ -0,0 +1,101 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.InvokeCommand", "DotNet.Revit.InvokeCommand\DotNet.Revit.InvokeCommand.csproj", "{F40BCA44-2737-4530-866C-B8ECB07696BE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ShortKey", "DotNet.Revit.ShortKey\DotNet.Revit.ShortKey.csproj", "{BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.GeometryObject", "DotNet.Revit.GeometryObject\DotNet.Revit.GeometryObject.csproj", "{61F38117-EB54-46B6-96BB-D62B3E0E599A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.Ribbon", "DotNet.Revit.Ribbon\DotNet.Revit.Ribbon.csproj", "{6519EF10-60A9-46DE-A14E-9B8787BCC5FC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ViewTransform", "DotNet.Revit.ViewTransform\DotNet.Revit.ViewTransform.csproj", "{748628B2-77B6-4C20-AE98-7C78F71386AB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ExternalEvent", "DotNet.Revit.ExternalEvent\DotNet.Revit.ExternalEvent.csproj", "{7164311A-01C1-4FAB-97DB-B9310C973800}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.NET", "DotNet.Revit.NET\DotNet.Revit.NET.csproj", "{A4D8216D-D414-4482-A1DC-98A972D09227}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Exchange.Revit", "DotNet.Exchange.Revit\DotNet.Exchange.Revit.csproj", "{22EDDE0F-0E6A-4C47-AEA5-17027830F236}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.Hook", "DotNet.Revit.Hook\DotNet.Revit.Hook.csproj", "{957A91DD-D04D-4811-82B7-7350A444CB12}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "frames", "frames", "{EED62B00-70DF-4A90-9EB3-DD11B848BDE1}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "DotNet.RevitUI", "DotNet.RevitUI\DotNet.RevitUI.shproj", "{824F3074-0794-4A6E-A2AD-36638408846C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.RevitUI (2016)", "DotNet.RevitUI (2016)\DotNet.RevitUI (2016).csproj", "{22F6CC59-E396-4477-9215-21777C68E044}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.DotNet.RevitUI (2016)", "Test.DotNet.RevitUI (2016)\Test.DotNet.RevitUI (2016).csproj", "{F4B2970D-431C-4801-A65D-F48FEE8C650A}"
+EndProject
+Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ DotNet.RevitUI\DotNet.RevitUI.projitems*{22f6cc59-e396-4477-9215-21777c68e044}*SharedItemsImports = 4
+ DotNet.RevitUI\DotNet.RevitUI.projitems*{824f3074-0794-4a6e-a2ad-36638408846c}*SharedItemsImports = 13
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Release|Any CPU.Build.0 = Release|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Release|Any CPU.Build.0 = Release|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {824F3074-0794-4A6E-A2AD-36638408846C} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {22F6CC59-E396-4477-9215-21777C68E044} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A} = {1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4212863E-A4CB-4F93-877C-346926AF014E}
+ EndGlobalSection
+EndGlobal
diff --git a/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj b/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj
new file mode 100644
index 0000000..6989ea4
--- /dev/null
+++ b/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj
@@ -0,0 +1,72 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {22F6CC59-E396-4477-9215-21777C68E044}
+ Library
+ Properties
+ DotNet.RevitUI
+ DotNet.RevitUI
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\AdWindows.dll
+ False
+
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\UIFramework.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\UIFrameworkServices.dll
+ False
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs b/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c38428e
--- /dev/null
+++ b/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("DotNet.RevitUI (2016)")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.RevitUI (2016)")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("22f6cc59-e396-4477-9215-21777c68e044")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.RevitUI/DotNet.RevitUI.projitems b/DotNet.RevitUI/DotNet.RevitUI.projitems
new file mode 100644
index 0000000..876422d
--- /dev/null
+++ b/DotNet.RevitUI/DotNet.RevitUI.projitems
@@ -0,0 +1,30 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 824f3074-0794-4a6e-a2ad-36638408846c
+
+
+ DotNet.RevitUI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.RevitUI/DotNet.RevitUI.shproj b/DotNet.RevitUI/DotNet.RevitUI.shproj
new file mode 100644
index 0000000..1e14f8f
--- /dev/null
+++ b/DotNet.RevitUI/DotNet.RevitUI.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 824f3074-0794-4a6e-a2ad-36638408846c
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/DotNet.RevitUI/Extension/WindowExtension.cs b/DotNet.RevitUI/Extension/WindowExtension.cs
new file mode 100644
index 0000000..b69cb6c
--- /dev/null
+++ b/DotNet.RevitUI/Extension/WindowExtension.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows;
+
+namespace DotNet.RevitUI.MVVM.Extension
+{
+ public static class WindowExtension
+ {
+ ///
+ /// 非模态显示窗体,并指定此窗体的宿主窗体.
+ ///
+ /// The main.
+ /// The parent.
+ public static void Show(this Window main, IntPtr parent)
+ {
+ if (parent == IntPtr.Zero)
+ {
+ parent = Process.GetCurrentProcess().MainWindowHandle;
+ }
+
+ var mainHelper = new System.Windows.Interop.WindowInteropHelper(main)
+ {
+ Owner = parent
+ };
+
+ // self-adaption
+ if (Math.Abs(PrimaryScreen.ScaleX - 1.0) >= 1e-7)
+ {
+ main.Width = main.Width * PrimaryScreen.ScaleX;
+ main.Height = main.Height * PrimaryScreen.ScaleX;
+ }
+
+ main.Show();
+ }
+
+ ///
+ /// 模态显示窗体,并指定此窗体的宿主窗体.
+ ///
+ public static void ShowDialog(this Window main, IntPtr parent)
+ {
+ if (parent == IntPtr.Zero)
+ {
+ parent = Process.GetCurrentProcess().MainWindowHandle;
+ }
+
+ var mainHelper = new System.Windows.Interop.WindowInteropHelper(main)
+ {
+ Owner = parent
+ };
+
+ // self-adaption
+ if (Math.Abs(PrimaryScreen.ScaleX - 1.0) >= 1e-7)
+ {
+ main.Width = main.Width * PrimaryScreen.ScaleX;
+ main.Height = main.Height * PrimaryScreen.ScaleX;
+ }
+
+ main.ShowDialog();
+ }
+
+ ///
+ /// 获取WPF窗口句柄.
+ ///
+ /// The main.
+ ///
+ public static IntPtr GetHandle(this Window main)
+ {
+ var helper = new System.Windows.Interop.WindowInteropHelper(main);
+
+#if !NET35
+ if(helper.Handle==IntPtr.Zero)
+ {
+ return helper.EnsureHandle();
+ }
+#endif
+ return helper.Handle;
+ }
+ }
+
+ class PrimaryScreen
+ {
+ #region Win32 API
+ [DllImport("user32.dll")]
+ static extern IntPtr GetDC(IntPtr ptr);
+
+ [DllImport("gdi32.dll")]
+ static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
+
+ [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
+ static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
+
+ #endregion
+
+ #region DeviceCaps常量
+ const int HORZRES = 8;
+ const int VERTRES = 10;
+ const int LOGPIXELSX = 88;
+ const int LOGPIXELSY = 90;
+ const int DESKTOPVERTRES = 117;
+ const int DESKTOPHORZRES = 118;
+ #endregion
+
+ #region 属性
+ ///
+ /// 获取屏幕分辨率当前物理大小
+ ///
+ public static Size WorkingArea
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var size = new Size
+ {
+ Width = GetDeviceCaps(hdc, HORZRES),
+ Height = GetDeviceCaps(hdc, VERTRES)
+ };
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return size;
+ }
+ }
+
+ ///
+ /// 当前系统DPI_X 大小 一般为96
+ ///
+ public static int DpiX
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var DpiX = GetDeviceCaps(hdc, LOGPIXELSX);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return DpiX;
+ }
+ }
+
+ ///
+ /// 当前系统DPI_Y 大小 一般为96
+ ///
+ public static int DpiY
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var DpiX = GetDeviceCaps(hdc, LOGPIXELSY);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return DpiX;
+ }
+ }
+
+ ///
+ /// 获取真实设置的桌面分辨率大小
+ ///
+ public static Size DESKTOP
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var size = new Size();
+ size.Width = GetDeviceCaps(hdc, DESKTOPHORZRES);
+ size.Height = GetDeviceCaps(hdc, DESKTOPVERTRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return size;
+ }
+ }
+
+ ///
+ /// 获取宽度缩放百分比
+ ///
+ public static float ScaleX
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var t = GetDeviceCaps(hdc, DESKTOPHORZRES);
+ var d = GetDeviceCaps(hdc, HORZRES);
+ var ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return ScaleX;
+ }
+ }
+
+ ///
+ /// 获取高度缩放百分比
+ ///
+ public static float ScaleY
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var scaleY = (float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return scaleY;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/DotNet.RevitUI/Helper/MainHelper.cs b/DotNet.RevitUI/Helper/MainHelper.cs
new file mode 100644
index 0000000..5f62cb6
--- /dev/null
+++ b/DotNet.RevitUI/Helper/MainHelper.cs
@@ -0,0 +1,51 @@
+using Autodesk.Windows;
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows;
+using UIFrameworkServices;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ /// Revit UI helper.
+ ///
+
+ public static class MainHelper
+ {
+ const int MDI_ID = 0x0000E900;
+
+ const int StatusBar_ID = 0x0000E801;
+
+ const int OptionsBar_ID = 0x000EC801;
+
+ [DllImport("user32")]
+ static extern IntPtr GetDlgItem(IntPtr hWndParent, int cid);
+
+ ///
+ /// Revit 主窗口句柄.
+ ///
+ public static IntPtr RevitHandle = ComponentManager.ApplicationWindow;
+
+ ///
+ /// Revit MDI句柄.
+ ///
+ public static IntPtr RevitMDIHandle = GetDlgItem(ComponentManager.ApplicationWindow, MDI_ID);
+
+ ///
+ /// Revit StatusBar句柄.
+ ///
+ public static IntPtr RevitStatusBarHandle = GetDlgItem(ComponentManager.ApplicationWindow, StatusBar_ID);
+
+ ///
+ /// Revit OptionsBar句柄
+ ///
+ public static IntPtr RevitOptionsBarHandle = GetDlgItem(ComponentManager.ApplicationWindow, OptionsBar_ID);
+
+ ///
+ /// Revit MDI rect.
+ ///
+ public static Rect RevitMDIRect = FloatingService.getMDIClientRect();
+ }
+}
\ No newline at end of file
diff --git a/DotNet.RevitUI/Helper/RevitCommandHelper.cs b/DotNet.RevitUI/Helper/RevitCommandHelper.cs
new file mode 100644
index 0000000..555ba60
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RevitCommandHelper.cs
@@ -0,0 +1,161 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UIFrameworkServices;
+using System.Reflection;
+using Autodesk.Revit.DB;
+using System.Windows.Threading;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ /// Revit command helper
+ ///
+ public class RevitCommandHelper
+ {
+ private static RevitCommandHelper m_Instance;
+
+ private ConcurrentDictionary m_CommandIds;
+
+ public static RevitCommandHelper Instance
+ {
+ get
+ {
+ return m_Instance;
+ }
+
+ internal set
+ {
+ m_Instance = value;
+ }
+ }
+
+ internal RevitCommandHelper()
+ {
+ m_Instance = this;
+
+ m_CommandIds = new ConcurrentDictionary();
+ }
+
+ ///
+ /// 指定一个基于IExternalCommand全名称.执行此命令.
+ ///
+ public bool Execute(string className)
+ {
+ if (!m_CommandIds.ContainsKey(className))
+ {
+ return false;
+ }
+
+ var commnadId = m_CommandIds[className];
+
+ string text2 = string.Format("CustomCtrl_%{0}%{1}", "ZhongHao.He", commnadId);
+
+ ExternalCommandHelper.executeExternalCommand(text2);
+
+ return true;
+ }
+
+ ///
+ /// 指定一个Revit命令接口,执行此命令.
+ ///
+ /// 在执行此命令之前,应确保命令已被加入.
+ public bool Execute()
+ where T : IExternalCommand
+ {
+ return this.Execute(typeof(T).FullName);
+ }
+
+ ///
+ /// 指定Revit命令Id,调用内部命令.
+ ///
+ public bool Invoke(string cmdId)
+ {
+ if (ExternalCommandHelper.CanExecute(cmdId))
+ {
+ ExternalCommandHelper.executeExternalCommand(cmdId);
+ return true;
+ }
+ else if (CommandHandlerService.canExecute(cmdId))
+ {
+ CommandHandlerService.invokeCommandHandler(cmdId);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 切回Revit上下文件环境调用命令.
+ ///
+ ///
+ public void Invoke(Action uiApp)
+ {
+ if (uiApp == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ if (Dispatcher.CurrentDispatcher != Autodesk.Windows.ComponentManager.Ribbon.Dispatcher)
+ {
+ Autodesk.Windows.ComponentManager.Ribbon.Dispatcher.Invoke(new Action(() =>
+ {
+ RevitCommandInvoke.InvokeHandlers.Enqueue(new InvokeHandler(uiApp));
+ this.Execute();
+
+ }));
+ }
+ else
+ {
+ RevitCommandInvoke.InvokeHandlers.Enqueue(new InvokeHandler(uiApp));
+ this.Execute();
+ }
+ }
+
+ ///
+ /// 注册一个命令.
+ ///
+ /// The assembly path.
+ /// Name of the class.
+ ///
+ public bool RegisterCommand(string assemblyPath, string className)
+ {
+ if (m_CommandIds.ContainsKey(className))
+ {
+ return false;
+ }
+
+ var guid = Guid.NewGuid().ToString();
+ var data = new PushButtonData(guid, guid, assemblyPath, className);
+ var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.InvokeMethod;
+
+ var btn = typeof(PushButtonData).InvokeMember("createPushButton",
+ flags,
+ Type.DefaultBinder,
+ null,
+ new object[] { data, false, "ZhongHao.He" });
+
+ btn.GetType().InvokeMember("getRibbonButton", flags, Type.DefaultBinder, btn, null);
+
+ return m_CommandIds.TryAdd(className, guid);
+ }
+
+ ///
+ /// 注册一个命令.
+ ///
+ ///
+ ///
+ public bool RegisterCommand()
+ where T : IExternalCommand
+ {
+ return RegisterCommand(typeof(T).Assembly.Location, typeof(T).FullName);
+ }
+ }
+}
diff --git a/DotNet.RevitUI/Helper/RibbonBindingHelper.cs b/DotNet.RevitUI/Helper/RibbonBindingHelper.cs
new file mode 100644
index 0000000..e1a90ff
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RibbonBindingHelper.cs
@@ -0,0 +1,211 @@
+using Autodesk.Windows;
+using Autodesk.Windows.ToolBars;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace DotNet.RevitUI.Helper
+{
+
+ class NonCommand : ICommand
+ {
+ public event EventHandler CanExecuteChanged;
+
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public void Execute(object parameter)
+ {
+ }
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+
+ public static class RibbonBindingHelper
+ {
+ ///
+ /// 自动关联绑定Ribbon子控件数据.
+ ///
+ /// The ribbon.
+ /// The data context.
+
+ public static void Binding(RibbonControl ribbon, object dataContext)
+ {
+ if (ribbon == null)
+ {
+ throw new NullReferenceException("ribbon parameter is null rference !");
+ }
+
+ if (ribbon.Tabs.Count == 0)
+ {
+ return;
+ }
+
+ if (dataContext == null)
+ {
+ dataContext = ribbon.DataContext;
+ }
+
+ if (dataContext == null)
+ {
+ return;
+ }
+
+ var eum = ribbon.Tabs.GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+
+ foreach (var panel in current.Panels)
+ {
+ ItemBinding(panel, dataContext);
+
+ if (panel.Source.DialogLauncher != null)
+ {
+ ItemBinding(panel.Source.DialogLauncher, dataContext);
+ }
+
+ foreach (var item in panel.Source.Items)
+ {
+ ItemRecursive(item, dataContext);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 递归遍历Item.
+ ///
+ /// The item.
+ /// The data context.
+
+ private static void ItemRecursive(RibbonItem item, object dataContext)
+ {
+ if (item == null)
+ {
+ return;
+ }
+
+ switch (item)
+ {
+ case RibbonListButton listButton:
+
+ listButton.CommandHandler = new NonCommand();
+
+ for (int i = 0; i < listButton.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(listButton.Items[i], dataContext);
+ }
+
+ break;
+
+ case ToolBarHistoryButton toolBar:
+
+ RibbonBindingHelper.ItemBinding(item, dataContext);
+
+ for (int i = 0; i < toolBar.Items.Count; i++)
+ {
+ var current = toolBar.Items[i] as RibbonItem;
+
+ if (current == null)
+ {
+ continue;
+ }
+
+ RibbonBindingHelper.ItemRecursive(current, dataContext);
+ }
+
+ break;
+ case RibbonMenuItem menuItem:
+
+ for (int i = 0; i < menuItem.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(menuItem.Items[i], dataContext);
+ }
+
+ break;
+
+ case RibbonList list:
+
+
+ for (int i = 0; i < list.Items.Count; i++)
+ {
+ var current = list.Items[i] as RibbonItem;
+
+ if (current == null)
+ {
+ continue;
+
+ }
+ RibbonBindingHelper.ItemRecursive(current, dataContext);
+ }
+
+ break;
+ case RibbonRowPanel rowPanel:
+
+ for (int i = 0; i < rowPanel.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(rowPanel.Items[i], dataContext);
+ }
+
+ break;
+ default:
+
+ RibbonBindingHelper.ItemBinding(item, dataContext);
+
+ break;
+ }
+ }
+
+ static void ItemBinding(object obj, object dataContext)
+ {
+ var properties = obj.GetType().GetProperties();
+
+ foreach (var property in properties)
+ {
+ var value = property.GetValue(obj, null);
+
+ if (value == null)
+ {
+ continue;
+ }
+
+ if (value is Binding binding)
+ {
+ if (string.IsNullOrEmpty(binding.Path.Path) || binding.Source != null)
+ {
+ continue;
+ }
+
+ try
+ {
+ binding.Source = dataContext;
+
+ if (obj is RibbonCommandItem commandItem
+ && property.Name == "CommandHandlerBinding")
+ {
+ commandItem.CommandParameter = obj;
+ }
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ Debug.WriteLine(ex.Message);
+#endif
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs b/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs
new file mode 100644
index 0000000..fedd3a2
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs
@@ -0,0 +1,117 @@
+
+using Autodesk.Windows;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Media;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ ///
+ ///
+ public static class RibbonRegisterHelper
+ {
+ ///
+ /// 基于指定泛型自动注册Ribbon下的Tab.
+ ///
+ ///
+ ///
+ public static T Register()
+ where T : FrameworkElement, new()
+ {
+ var frameworkElement = new T();
+
+ var flag = RibbonRegisterHelper.Register(frameworkElement);
+
+ if (flag)
+ {
+ return frameworkElement;
+ }
+
+ return default(T);
+ }
+
+ ///
+ /// 基于指定控件自动注册Ribbon下的Tab.
+ ///
+ /// The framework element.
+ ///
+ public static bool Register(FrameworkElement frameworkElement)
+ {
+ var mainRibbon = Autodesk.Windows.ComponentManager.Ribbon;
+
+ if (mainRibbon == null)
+ {
+ return false;
+ }
+
+ var ribbons = new List>();
+
+ if (frameworkElement is RibbonControl ribbon)
+ {
+ ribbons.Add(new KeyValuePair(ribbon, ribbon.DataContext));
+ }
+ else
+ {
+ var temps = new List();
+
+ frameworkElement.GetRibbonControl(ref temps);
+
+ foreach (var item in temps)
+ {
+ var dataContext = frameworkElement.DataContext;
+ if (dataContext == null)
+ {
+ dataContext = item.DataContext;
+ }
+
+ ribbons.Add(new KeyValuePair(item, dataContext));
+ }
+ }
+
+ if (ribbons.Count == 0)
+ {
+ return false;
+ }
+
+ var eum = ribbons.GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var tabs = eum.Current.Key.Tabs;
+
+ RibbonBindingHelper.Binding(eum.Current.Key, eum.Current.Value);
+
+ foreach (var item in tabs)
+ {
+ mainRibbon.Tabs.Add(item);
+ }
+ }
+ return true;
+ }
+
+ static void GetRibbonControl(this DependencyObject obj, ref List ribbons)
+ {
+ var eum = LogicalTreeHelper.GetChildren(obj).GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+
+ if (current is RibbonControl)
+ {
+ ribbons.Add((RibbonControl)current);
+ }
+
+ if (current is DependencyObject depend)
+ {
+ GetRibbonControl(depend, ref ribbons);
+ }
+ }
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/IExecuteWithObject.cs b/DotNet.RevitUI/MVVM/IExecuteWithObject.cs
new file mode 100644
index 0000000..a2d50a9
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/IExecuteWithObject.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ interface IExecuteWithObject
+ {
+ object Target
+ {
+ get;
+ }
+
+ void ExecuteWithObject(object parameter);
+
+ void MarkForDeletion();
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/IMessenger.cs b/DotNet.RevitUI/MVVM/IMessenger.cs
new file mode 100644
index 0000000..07fa5d7
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/IMessenger.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ public interface IMessenger
+ {
+ void Register(object recipient, Action action);
+
+ void Register(object recipient, object token, Action action);
+
+ void Register(object recipient, object token, bool receiveDerivedMessagesToo, Action action);
+
+ void Register(object recipient, bool receiveDerivedMessagesToo, Action action);
+
+ void Send(TMessage message);
+
+ void Send(TMessage message);
+
+ void Send(TMessage message, object token);
+
+ void Unregister(object recipient);
+
+ void Unregister(string token);
+
+ void Unregister(object recipient);
+
+ void Unregister(object recipient, object token);
+
+ void Unregister(object recipient, Action action);
+
+ void Unregister(object recipient, object token, Action action);
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/Messenger.cs b/DotNet.RevitUI/MVVM/Messenger.cs
new file mode 100644
index 0000000..417dbe7
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/Messenger.cs
@@ -0,0 +1,386 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+
+namespace DotNet.RevitUI.MVVM
+{
+ public class Messenger : IMessenger
+ {
+ private static readonly object CreationLock = new object();
+ private static IMessenger m_DefaultInstance;
+ private readonly object m_RegisterLock = new object();
+ private Dictionary> m_RecipientsOfSubclassesAction;
+ private Dictionary> m_RecipientsStrictAction;
+
+ ///
+ /// 单例.
+ ///
+ public static IMessenger Default
+ {
+ get
+ {
+ if (m_DefaultInstance == null)
+ {
+ lock (CreationLock)
+ {
+ if (m_DefaultInstance == null)
+ {
+ m_DefaultInstance = new Messenger();
+ }
+ }
+ }
+ return m_DefaultInstance;
+ }
+ }
+
+
+
+ public virtual void Register(object recipient, Action action)
+ {
+ Register(recipient, null, false, action);
+ }
+
+ public virtual void Register(object recipient, bool receiveDerivedMessagesToo, Action action)
+ {
+ Register(recipient, null, receiveDerivedMessagesToo, action);
+ }
+
+ public virtual void Register(object recipient, object token, Action action)
+ {
+ Register(recipient, token, false, action);
+ }
+
+ public virtual void Register(object recipient, object token, bool receiveDerivedMessagesToo, Action action)
+ {
+ lock (m_RegisterLock)
+ {
+ var messageType = typeof(TMessage);
+
+ Dictionary> recipients;
+
+ if (receiveDerivedMessagesToo)
+ {
+ if (m_RecipientsOfSubclassesAction == null)
+ {
+ m_RecipientsOfSubclassesAction = new Dictionary>();
+ }
+
+ recipients = m_RecipientsOfSubclassesAction;
+ }
+ else
+ {
+ if (m_RecipientsStrictAction == null)
+ {
+ m_RecipientsStrictAction = new Dictionary>();
+ }
+
+ recipients = m_RecipientsStrictAction;
+ }
+
+ lock (recipients)
+ {
+ List list;
+
+ if (!recipients.ContainsKey(messageType))
+ {
+ list = new List();
+ recipients.Add(messageType, list);
+ }
+ else
+ {
+ list = recipients[messageType];
+ }
+
+ var weakAction = new WeakAction(recipient, action);
+
+ var item = new WeakActionAndToken
+ {
+ Action = weakAction,
+ Token = token
+ };
+
+ list.Add(item);
+ }
+ }
+
+ RequestCleanup();
+ }
+
+ private bool _isCleanupRegistered;
+
+ public virtual void Send(TMessage message)
+ {
+ SendToTargetOrType(message, null, null);
+ }
+
+ public virtual void Send(TMessage message)
+ {
+ SendToTargetOrType(message, typeof(TTarget), null);
+ }
+
+ public virtual void Send(TMessage message, object token)
+ {
+ SendToTargetOrType(message, null, token);
+ }
+
+ public virtual void Unregister(object recipient)
+ {
+ UnregisterFromListsByRecipient(recipient, m_RecipientsOfSubclassesAction);
+ UnregisterFromListsByRecipient(recipient, m_RecipientsStrictAction);
+ }
+
+ public void Unregister(string token)
+ {
+ UnregisterFromListsByToken(token, m_RecipientsOfSubclassesAction);
+ UnregisterFromListsByToken(token, m_RecipientsStrictAction);
+ }
+
+ public virtual void Unregister(object recipient)
+ {
+ Unregister(recipient, null, null);
+ }
+
+ public virtual void Unregister(object recipient, object token)
+ {
+ Unregister(recipient, token, null);
+ }
+
+ public virtual void Unregister(object recipient, Action action)
+ {
+ Unregister(recipient, null, action);
+ }
+
+ public virtual void Unregister(object recipient, object token, Action action)
+ {
+ UnregisterFromLists(recipient, token, action, m_RecipientsStrictAction);
+ UnregisterFromLists(recipient, token, action, m_RecipientsOfSubclassesAction);
+ RequestCleanup();
+ }
+
+
+ public static void OverrideDefault(IMessenger newMessenger)
+ {
+ m_DefaultInstance = newMessenger;
+ }
+
+ public static void Reset()
+ {
+ m_DefaultInstance = null;
+ }
+
+ public void ResetAll()
+ {
+ Reset();
+ }
+
+ public void RequestCleanup()
+ {
+ if (!_isCleanupRegistered)
+ {
+ Action cleanupAction = Cleanup;
+
+ System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(cleanupAction, System.Windows.Threading.DispatcherPriority.ApplicationIdle, null);
+ _isCleanupRegistered = true;
+ }
+ }
+
+ public void Cleanup()
+ {
+ CleanupList(m_RecipientsOfSubclassesAction);
+ CleanupList(m_RecipientsStrictAction);
+ _isCleanupRegistered = false;
+ }
+
+ private static void CleanupList(IDictionary> lists)
+ {
+ if (lists == null)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ var listsToRemove = new List();
+ foreach (var list in lists)
+ {
+ var recipientsToRemove = list.Value
+ .Where(item => item.Action == null || !item.Action.IsAlive)
+ .ToList();
+
+ foreach (var recipient in recipientsToRemove)
+ {
+ list.Value.Remove(recipient);
+ }
+
+ if (list.Value.Count == 0)
+ {
+ listsToRemove.Add(list.Key);
+ }
+ }
+
+ foreach (var key in listsToRemove)
+ {
+ lists.Remove(key);
+ }
+ }
+ }
+
+ private static void SendToList(TMessage message, IEnumerable weakActionsAndTokens, Type messageTargetType, object token)
+ {
+ if (weakActionsAndTokens != null)
+ {
+ // Correction Messaging BL0004.007
+ var list = weakActionsAndTokens.ToList();
+ var listClone = list.Take(list.Count()).ToList();
+
+ foreach (var item in listClone)
+ {
+ var executeAction = item.Action as IExecuteWithObject;
+
+ if (executeAction != null
+ && item.Action.IsAlive
+ && item.Action.Target != null
+ && (messageTargetType == null
+ || item.Action.Target.GetType() == messageTargetType
+ || messageTargetType.IsAssignableFrom(item.Action.Target.GetType()))
+ && ((item.Token == null && token == null)
+ || item.Token != null && item.Token.Equals(token)))
+ {
+ executeAction.ExecuteWithObject(message);
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromListsByToken(object token, Dictionary> lists)
+ {
+ if (token == null || lists == null || lists.Count == 0)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var messageType in lists.Keys)
+ {
+ foreach (var item in lists[messageType])
+ {
+ if (item.Action != null && item.Token == token)
+ {
+ item.Action.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromListsByRecipient(object recipient, Dictionary> lists)
+ {
+ if (recipient == null || lists == null || lists.Count == 0)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var messageType in lists.Keys)
+ {
+ foreach (var item in lists[messageType])
+ {
+ var weakAction = (IExecuteWithObject)item.Action;
+
+ if (weakAction != null
+ && recipient == weakAction.Target)
+ {
+ weakAction.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromLists(object recipient, object token, Action action, Dictionary> lists)
+ {
+ var messageType = typeof(TMessage);
+
+ if (recipient == null || lists == null || lists.Count == 0 || !lists.ContainsKey(messageType))
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var item in lists[messageType])
+ {
+ if (item.Action is WeakAction)
+ {
+ var weakActionCasted = item.Action as WeakAction;
+
+ if (recipient == weakActionCasted.Target
+ && (action == null || action.Method.Name == weakActionCasted.MethodName)
+ && (token == null || token.Equals(item.Token)))
+ {
+ item.Action.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+
+ private void SendToTargetOrType(TMessage message, Type messageTargetType, object token)
+ {
+ var messageType = typeof(TMessage);
+
+ if (m_RecipientsOfSubclassesAction != null)
+ {
+ var listClone = m_RecipientsOfSubclassesAction.Keys.Take(m_RecipientsOfSubclassesAction.Count()).ToList();
+
+ foreach (var type in listClone)
+ {
+ List