Показаны сообщения с ярлыком WinForms. Показать все сообщения
Показаны сообщения с ярлыком WinForms. Показать все сообщения

NotifyIcon в WPF приложении

суббота, 11 июля 2009 г.,

Задача: после запуска WPF Application в system tray, т.е. в правом нижнем углу экрана должна появиться иконка; при щелчке мышью по иконке надо показать окно; закрытие окон не должно приводить к закрытию приложения.

Реализовать иконку в system tray можно с помощью NotifyIcon; для этого в References проекта WPF Application надо:
  1. добавить сборку System.Windows.Forms.dll
  2. в App.xaml у тега Application убрать атрибут StartupUri
  3. в App.cs в class App добавить конструктор
    public App()
    {
        // закрытие всех окон приложения не приводит к его завершению
        this.ShutdownMode = ShutdownMode.OnExplicitShutdown;

        // создать иконку и поместить ее в system tray
        var ni = new System.Windows.Forms.NotifyIcon();
        ni.Visible = true;
        ni.Icon = WpfApplication6.Properties.Resources.Icon1;

        ni.Click += (s, _) =>
        {
            // создать и показать окно
            var uri = new Uri("Window1.xaml", UriKind.Relative);
            var wnd = Application.LoadComponent(uri) as Window;
            wnd.Visibility = Visibility.Visible;
            wnd.ShowInTaskbar = false;
        };

        // определить контекстное меню
        ni.ContextMenu = new System.Windows.Forms.ContextMenu(new[]
        {
            // завершить приложение
            new System.Windows.Forms.MenuItem("Exit", delegate
            {
                ni.Visible = false;
               this.Shutdown();
            })
        });
    }
Надо заметить, что если приложение будет закрыто по ошибке или из дебаггера, то иконка останется в system tray до тех пор пока над ней не окажется курсор мыши.

Перехват событий Silverlight в WinForms

понедельник, 13 апреля 2009 г.,

Silverlight можно использовать в WinForms-приложении не только для вывода Xaml. Также можно перехватывать сообщения, которые создаются в Silverlight.

За основу возьмем пример из сообщения "Silverlight в WinForms". Добавим в него неполное определение интерфейса IXcpControl (интерфейс наследует IDispatch, поэтому необязательно импортировать все свойства и методы):
[ComImport, Guid("1FB839CC-116C-4C9B-AE8E-3DBB6496E326"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch), ComVisible(true)]
public interface IXcpControl
{
    [DispId(0x20)]
    string Source { get; set; }

    [DispId(0x2c)]
    object OnLoad { get; set; }
}

И добавим наследника IReflect (используется в качестве посредника между Silverlight и WinForms; также можно использовать вместе с JavaScript):
public class Handler : IReflect
{
    public EventHandler _EventHandler;
    public Handler(EventHandler eh)
    {
        _EventHandler = eh;
    }

    [DispId(0)]
    public void Method()
    {
        if (_EventHandler != null)
            _EventHandler(this, EventArgs.Empty);
    }

    object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
    {
        if (name.Equals("[DISPID=0]", StringComparison.OrdinalIgnoreCase))
        {
            this.Method();
            return null;
        }
        throw new MissingMethodException(base.GetType().Name, name);
    }

    PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) { return new PropertyInfo[0]; }
    MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) { return new MethodInfo[0]; }
    FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) { return new FieldInfo[0]; }
    MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) { return new MemberInfo[0]; }
    MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { return null; }
    FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) { return null; }
    MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) { return null; }
    MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) { return null; }
    PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { return null; }
    PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) { return null; }
    Type IReflect.UnderlyingSystemType { get { return null; } }
}

Теперь надо создать форму и в ее конструктор поместить следующий код:
this.Size = new Size((int)(SystemInformation.WorkingArea.Width * .50f), 400);
string html = @"
    <SCRIPT id='_Xaml' type='text/xaml'>
        <?xml version='1.0' encoding='utf-8' ?>
        <Canvas
            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
                <TextBlock FontSize='40' Foreground='Red'>Hello, World!</TextBlock>
        </Canvas>
    </SCRIPT>
    <OBJECT ID='_Ag' data='data:application/x-silverlight,' type='application/x-silverlight' Width='100%' Height='100%'>
        <PARAM NAME='Background' VALUE='#FFFADF' />
    </OBJECT>";
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += delegate
{
    var ag = wb.Document.GetElementById("_Ag").DomElement as IXcpControl;
    ag.OnLoad = new Handler(delegate { MessageBox.Show("Done!"); });
    ag.Source = "#_Xaml";
};

wb.DocumentText = html;
wb.Dock = DockStyle.Fill;
wb.Parent = this;
WebBrowser загрузит html и вызовет обработчик события DocumentCompleted. К событию OnLoad будет подключен обработчик, который вызовется из Silverlight после завершения загрузки xaml.

Как встроить Word в WinForms или веб-страницу


Word, Excel, Visio, PowerPoint можно встроить в Windows Forms Application или веб-страницу с помощью DSOFramer (это ActiveX), который входит в состав Microsoft Developer Support Office Framer Control 1.3 Sample (KB 311765).

После установки примеров (C:\DsoFramer) надо: 1) в Visual Studio создать новый проект (Windows Forms Application); 2) В References добавить ссылку на C:\DsoFramer\dsoframer.ocx (в результате будет создан файл Interop.DSOFramer.dll; в References появится DSOFramer); 3) Добавить в проект класс:
public class Fcc : AxHost
{
    public Fcc()
        : base("00460182-9E5E-11d5-B7C8-B8269041DD57")
    {
    }
}
4) Код конструктора Form1 заменить на следующий:
this.Size = new Size((int)(SystemInformation.WorkingArea.Width * .90f), 400);
this.Shown += delegate
{
    var fcc = new Fcc();
    fcc.Dock = DockStyle.Fill;
    fcc.Parent = this;

    var ocx = fcc.GetOcx() as FramerControl;
    ocx.Titlebar = false;
    ocx.Toolbars = false;
    ocx.Menubar = false;
    ocx.EventsEnabled = true;

    ocx.Open(@"C:\Temp\Test.docx", Missing.Value, Missing.Value, Missing.Value, Missing.Value);
    ocx.Activate();
};
Метод ocx.Open также можно вызвать следующим способом:
typeof(_FramerControl).GetMethod("Open").Invoke(ocx, new object[] { @"C:\Temp\Test.docx", Missing.Value, Missing.Value, Missing.Value, Missing.Value });
5) Заменить "C:\Temp\Test.docx" на путь к файлу с расширением: .docx | .doc | .pptx | ... Нажать F5.


Чтобы самому не создавать наследника AxHost, можно сделать следующее: 1) Открыть Form1.cs в дизайнере (= в контекстном меню выбрать View Designer); 2) Открыть Toolbox (Ctrl+W, X); 3) В контекстном меню Toolbox'а выбрать Choose Items... - COM Components; 4) В списке найти DSO Framer Control Object, включить checkbox; 5) DSO Framer Control Object перетащить с Toolbar'а и сбросить над формой.
В результате будет создан файл AxInterop.DSOFramer.dll, а в References появится AxDSOFramer.

Пример встраивания офисных документов в веб-страницу находится в папке C:\DsoFramer\Samples\WebTest

Подробности использования DSOFramer приведены в статье "Visual C++ ActiveX Control for hosting Office documents in Visual Basic or HTML".

Silverlight в WinForms

понедельник, 6 апреля 2009 г.,

Silverlight можно запустить в WinForms-приложении. Для этого надо: 1) Создать Windows Forms Application; 2) В References добавить "C:\Program Files\Microsoft Silverlight\3.0.40307.0\npctrl.dll" (появится XcpControlLib); 3) В конструктор формы добавить следующий код:

string html = @"
        <BODY STYLE='margin: 0px; padding: 0px;'>
            <SCRIPT TYPE='text/javascript'>
            function onSilverlightError(sender, args)
            {
                alert(args.errorMessage + ' ' + args.errorType);
            }
            </SCRIPT>
            <SCRIPT id='_Xaml' type='text/xaml'>
                <?xml version='1.0' encoding='utf-8' ?>
                <Canvas
                    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
                        <TextBlock FontSize='40' Foreground='Red'>Hello, World!</TextBlock>
                </Canvas>
            </SCRIPT>
            <OBJECT ID='_Ag' CLASSID='clsid:DFEAF541-F3E1-4C24-ACAC-99C30715084A' Width='100%' Height='100%'>
                <PARAM NAME='Background' VALUE='#FFFADF' />
                <PARAM NAME='onerror' VALUE='onSilverlightError' />
                <PARAM NAME='Source' VALUE='#_Xaml' />
            </OBJECT>
        </BODY>";

WebBrowser wb = new WebBrowser();
wb.Dock = DockStyle.Fill;
wb.DocumentText = html;
wb.Parent = this;

Есть одно ограничение: в xaml нельзя использовать, например, Button; получим exception: "ParserError: Unknown element: Button". Причина в том, что Button определен в System.Windows.Controls (System.Windows.dll); Для использования контролов из Silverlight (старше 1) требуется компиляция; в результате будет создан .xap-файл, который необходимо загрузить в Silverlight.