2015-09-01 14 views
6

मुझे पूरा यकीन है कि इस सवाल को वेब के चारों ओर बहुत कुछ पूछा गया है और मैंने कई फ़ोरम पर कई प्रश्न और उनके "उत्तर" पढ़े हैं लेकिन मैंने कभी स्पष्ट उत्तर नहीं देखा है तो मैं जानना चाहते हैं:वीबीए विंडोज 7 स्टाइल बटन

संभव है, उपयोग करने के लिए विंडोज 7 शैली बटन

enter image description here

एक्सेल VBA में

या मैं देख इन ग्रे चीजों का उपयोग करने की तरह वे

से आते हैं की क्या ज़रूरत है

enter image description here

?

I छवियों का उपयोग करना चाहते हैं, मेरा मतलब है कि इन "ActiveX नियंत्रण" को आयात करना, मुझे लगता है कि उनका नाम है।

+0

मुझे यह भी जानना अच्छा लगेगा। – DeerSpotter

+6

* क्या मुझे इन ग्रे चीजों का उपयोग करना है जैसे वे विंडोज 2000 * से आते हैं - मुझे लगता है कि वे वास्तव में Win95 से हैं। यदि आप * चमकदार और नया * चाहते हैं, तो आप अपने यूआई को COM-visible .net क्लास लाइब्रेरी (.dll) में WPF/XAML के साथ बना सकते हैं, और * V * को अपने वीबीए कोड से उपयोग कर सकते हैं। आपकी कोडिंग शैली के आधार पर यह * गंभीर वास्तुशिल्प परिवर्तनों का अर्थ हो सकता है (यानी यदि आप बटन 'क्लिक' हैंडलर में सभी तर्क लागू करने के लिए उपयोग किए जाते हैं ...) –

+6

अनुवाद: यदि आप पर्याप्त प्रोग्रामिंग करने में सक्षम होने के बारे में जानते थे यह, आप जानते होंगे कि आप नहीं चाहते हैं। – Kaz

उत्तर

3

अप सीट, आप एक सवारी के लिए कर रहे हैं।


सबसे पहले, एक नया सी # बनाने के (या VB.NET .. जो कुछ भी अपनी नाव चट्टानों) वर्ग पुस्तकालय, और एक नया WPF UserControl जोड़ देंगे और अपने यूआई डिजाइन:

<UserControl x:Class="ComVisibleUI.UserControl1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" d:DataContext="ViewModel1" 
      d:DesignHeight="200" d:DesignWidth="300"> 

    <Grid Background="White"> 

     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="32" /> 
     </Grid.RowDefinitions> 

     <TextBlock Text="actual content here" Foreground="DimGray" HorizontalAlignment="Center" VerticalAlignment="Center" /> 

     <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="2"> 
      <Button Width="128" Command="{Binding Command1}"> 
       <TextBlock Text="Button1" /> 
      </Button> 
      <Button Width="128" Command="{Binding Command2}"> 
       <TextBlock Text="Button2" /> 
      </Button> 
     </StackPanel> 

    </Grid> 
</UserControl> 

बिल्ड परियोजना।

फिर, नई विधि जोड़ें एक WPF इंटरॉप ElementHost नियंत्रण गोदी, और आप की मेजबानी WPF नियंत्रण के रूप में अपने WPF UserControl1 (जो भी आप यह कहा जाता है) को जोड़ने के लिए सक्षम होना चाहिए। है, तो आप प्रबंधित कोड लागू करने के लिए एक वर्ग की आवश्यकता होगी -

WPF नियंत्रण (मॉडल-व्यू-ViewModel तर्ज पर पढ़ वास्तव में किसी और और सब कुछ,) Command1 और Command2 ऊपर हुक करने के लिए डेटा बाइंडिंग का उपयोग करता है भाग।यदि आपका तर्क सभी VBA है तो यह बहुत पतला होना चाहिए:

public class ViewModel1 
{ 
    public ViewModel1() 
    { 
     _command1 = new DelegateCommand(ExecuteCommand1); 
     _command2 = new DelegateCommand(ExecuteCommand2); 
    } 

    private readonly ICommand _command1; 
    public ICommand Command1 { get { return _command1; } } 

    public event EventHandler ExecutingCommand1; 
    private void ExecuteCommand1(object parameter) 
    { 
     ExecuteHandler(ExecutingCommand1); 
    } 

    private readonly ICommand _command2; 
    public ICommand Command2 { get { return _command2; } } 

    public event EventHandler ExecutingCommand2; 
    private void ExecuteCommand2(object parameter) 
    { 
     ExecuteHandler(ExecutingCommand2); 
    } 

    private void ExecuteHandler(EventHandler eventHandler) 
    { 
     var handler = eventHandler; 
     if (handler != null) 
     { 
      handler.Invoke(this, EventArgs.Empty); 
     } 
    } 
} 

एक DelegateCommand एक बहुत ही अच्छी छोटी बात सभी स्टैक ओवरफ़्लो हो चुका है है, तो आप कोई प्रश्न हैं खोज करने के लिए संकोच नहीं करते:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    public void SetDataContext(ViewModel1 viewModel) 
    { 
     hostedWPFControl.DataContext = viewModel; 
    } 
} 
: ऐसा करने के लिए एक विधि का पर्दाफाश -
public class DelegateCommand : ICommand 
{ 
    private readonly Action<object> _execute; 
    private readonly Func<object, bool> _canExecute; 

    public DelegateCommand(Action<object> execute, Func<object,bool> canExecute = null) 
    { 
     _execute = execute; 
     _canExecute = canExecute; 
    } 

    public event EventHandler CanExecuteChanged; 
    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null ? true : _canExecute.Invoke(parameter); 
    } 

    public void Execute(object parameter) 
    { 
     _execute.Invoke(parameter); 
    } 
} 

WinForms विधि निर्दिष्ट करने के WPF नियंत्रण के DataContext की आवश्यकता होगी 0

इसके अलावा, यहां कोई भी कोड नहीं होना चाहिए


WPF MVVM पैटर्न पसंद करती है, WinForms एमवीपी (देखने मॉडल-व्यू-प्रस्तुतकर्ता) पसंद करती है।

[ComVisible(true)] 
public interface IPresenter1 
{ 
    void Show(); 
} 

हाँ, वह सिर्फ एक इंटरफ़ेस है: उस वस्तु VBA कोड का उपयोग करेगा है - WPF हिस्सा WinForms में होस्ट किया जा रहा है, हम एक प्रस्तोता बना देंगे। पर रखें, हम एक और की जरूरत है:

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
[Guid("18F3B8A8-EC60-4BCE-970A-6C0ABA145705")] 
[ComVisible(true)] 
public interface IPresenterEvents 
{ 
    void ExecuteCommand1(object message); 
    void ExecuteCommand2(); 
} 

IPresenterEvents इंटरफ़ेस आपके "घटना सिंक" इंटरफेस है, कि VBA कोड को लागू करने की आवश्यकता होगी, लेकिन मैं इसे करने के लिए मिल जाएगा। पहले हम वास्तविक प्रस्तोता implment की जरूरत है:

public delegate void Command1Delegate(string message); 
public delegate void Command2Delegate(); 

[ComSourceInterfaces(typeof(IPresenterEvents))] 
[ClassInterface(ClassInterfaceType.None)] 
[ComVisible(true)] 
[Guid("FAF36F86-7CB3-4E0C-A016-D8C84F6B07D7")] 
public class Presenter1 : IPresenter1, IDisposable 
{ 
    private readonly Form _view; 

    public Presenter1() 
    { 
     var view = new Form1(); 
     var viewModel = new ViewModel1(); 
     viewModel.ExecutingCommand1 += viewModel_ExecutingCommand1; 
     viewModel.ExecutingCommand2 += viewModel_ExecutingCommand2; 

     view.SetDataContext(viewModel); 

     _view = view; 
    } 

    public event Command1Delegate ExecuteCommand1; 
    private void viewModel_ExecutingCommand1(object sender, EventArgs e) 
    { 
     var handler = ExecuteCommand1; 
     if (handler != null) 
     { 
      handler.Invoke("Hello from Command1!"); 
     } 
    } 

    public event Command2Delegate ExecuteCommand2; 
    private void viewModel_ExecutingCommand2(object sender, EventArgs e) 
    { 
     var handler = ExecuteCommand2; 
     if (handler != null) 
     { 
      handler.Invoke(); 
     } 
    } 

    public void Show() 
    { 
     _view.ShowDialog(); 
    } 

    public void Dispose() 
    { 
     _view.Dispose(); 
    } 
} 

अब, परियोजना के गुण होते हैं और फिर जाँच करें कि चेकबॉक्स "COM इंटरॉप के लिए रजिस्टर", तो परियोजना का निर्माण; [डीबग] टैब में, का चयन करें "बाहरी प्रोग्राम प्रारंभ करें" शुरू करें, और अपनी मशीन पर EXCEL.EXE निष्पादन योग्य का पता लगाएं: जब आप F5 दबाते हैं, विजुअल स्टूडियो एक्सेल लॉन्च डीबगर के साथ लॉन्च करेगा, और फिर आप खोल सकते हैं वीबीई (Alt + F11), जिसे आपने अभी बनाया है .tlb (टाइप लाइब्रेरी) का संदर्भ जोड़ें (आप इसे \bin\debug\theprojectname.tlb के तहत, अपनी डीनेट प्रोजेक्ट निर्देशिका में पाएंगे, डीबग बिल्ड मानते हैं), और इसे करना चाहिए ।

वहाँ कई मुद्दों यहाँ है कि मैं वापस आऊँगा बाद में तय करने के लिए कर रहे हैं,:

  • Dispose() विधि उजागर नहीं है, और स्पष्ट या परोक्ष, किसी भी बिंदु पर नहीं कहा जा होगा जो गन्दा है।
  • हालांकि सब कुछ ऐसा लगता है जैसे यह सी # डीबगर के दृष्टिकोण से काम कर रहा है, मुझे डर्न वीबीए हैंडलर चलाने के लिए नहीं मिल सका। यदि आप वीबीए में तर्क को लागू करना चाहते हैं तो यह शायद एक बड़ी समस्या है, न केवल यूआई लाएं। ओटीओएच आपके पास .NET कोड तक पहुंच है, साथ ही प्रस्तुतकर्ता में प्रस्तुतकर्ता तर्क को सी #/वीबी.नेट में भी लागू कर सकता है, और फिर आपको इन ईवेंट हैंडलर को काम करने की आवश्यकता नहीं है।

वैसे भी, मैं ThisWorkbook लिए इस कोड को जोड़ दिया है:

Option Explicit 
Private WithEvents view As ComVisibleUI.Presenter1 

Public Sub DoSomething() 
    Set view = New ComVisibleUI.Presenter1 
    view.Show 
End Sub 

Private Sub view_ExecuteCommand1(ByVal message As Variant) 
    MsgBox message 
End Sub 

Private Sub view_ExecuteCommand2() 
    MsgBox "Hello from WPF!" 
End Sub 

और जब मैं तत्काल खिड़की (Ctrl + G) से ThisWorkbook.DoSomething चलाने के लिए, मैं इस मिल:

WPF-powered UI with shiny command buttons

सिद्धांत में (कम से कम MSDN के अनुसार), आपको बस इतना करना है। जैसा कि मैंने कहा था कि इन घटनाओं के हैंडलर किसी कारण से नहीं बुला रहे हैं, लेकिन हे, आपको अपने चमकदार बटन मिलते हैं! ... और अब आपके यूआई को डिज़ाइन करने के लिए डब्ल्यूपीएफ की सभी शक्ति :)

+1

पवित्र ओ.ओ प्रयासों के लिए धन्यवाद, मैं इसे कुछ दिनों में कोशिश करूंगा और आपको यह बताएगा कि यह काम करता है या नहीं –

5

मुझे ऐसे समाधान से अनजान है जहां आप "विंडोज 7 स्टाइल बटन" का उपयोग कर सकते हैं। फिर भी, मैं यह ध्यान रखना चाहूंगा कि प्रोग्रामिंग आपको विशेष रूप से "डेवलपर" टैब का उपयोग करने की आवश्यकता नहीं है। दूसरे शब्दों में: सिर्फ इसलिए कि आप एक बटन चाहते हैं इसका मतलब यह नहीं है कि आपको केवल डेवलपर टैब से उपयोग करना होगा। वास्तव में, एक्सेल के भीतर लगभग किसी भी आकार को मैक्रो असाइन किया जा सकता है।

एक बटन "विंडोज 7 शैली बटन" के समान प्राप्त करने के लिए सबसे आसान तरीका है Insert एक Rectangle या एक Rounded RectangleShapes मेनू से किया जा सके। जब आप उस आकार पर क्लिक करते हैं तो उस "फैंसी" ग्रे रंग को आसानी से हासिल किया जा सकता है और फिर उस आकार के Format टैब पर पूर्वनिर्धारित ग्रे-स्केल shape style में से एक का चयन करें। ये बटन आप जो चाहते हैं उसके समान ही दिखते हैं और इन आकारों पर राइट-क्लिक करके आसानी से assigned a macro हो सकते हैं।

A comparison of buttons created with Excel shapes to the standard Windows 7 button

+0

+ के उपयोगकर्ताफॉर्म में ++ वर्कशीट पर एक बटन वास्तव में वर्कशीट के 'आकार' संग्रह में संग्रहीत होता है; यह समाधान अब तक का सबसे सरल है, और आप प्रभाव और ड्रॉप-छाया के साथ बहुत साफ परिणाम प्राप्त कर सकते हैं। –

+0

"आकार मेनू" के साथ आपका क्या मतलब है? –

+0

'सम्मिलित करें' -> 'चित्र' -> आकार '->' आयत आयताकार 'या' आयताकार' – Ralph