Showing posts with label Winforms. Show all posts
Showing posts with label Winforms. Show all posts

Tuesday, May 17, 2011

Synchronized RichTextBox objects (or how to scroll 2 RichTextBox objects together)

In my previous posts I have described, how to create synchronized (or linked) ListBox and ListView objects. Now I continue in investigation in this area and I have found another interesting example which describes synchronization of two RichTextBox objects. First step is to create class which derives from RichTextBox class.
public class SynchronizedScrollRichTextBox : System.Windows.Forms.RichTextBox
{
    public event vScrollEventHandler vScroll;
    public delegate void vScrollEventHandler(System.Windows.Forms.Message message);

    public const int WM_VSCROLL = 0x115;

    protected override void WndProc(ref System.Windows.Forms.Message msg)
    {
        if (msg.Msg == WM_VSCROLL)
        {
            if (vScroll != null)
            {
                vScroll(msg);
            }
        }
        base.WndProc(ref msg);
    }

    public void PubWndProc(ref System.Windows.Forms.Message msg)
    {
        base.WndProc(ref msg);
    }
}
I have created two SynchronizedScrollRichTextBox controls and placed them on the form. Then I have added following code (vScroll event):
private void synchronizedScrollRichTextBox1_vScroll(Message message)
{
    message.HWnd = synchronizedScrollRichTextBox2.Handle;
    synchronizedScrollRichTextBox2.PubWndProc(ref message);
}
Here you can find original post.

Monday, May 16, 2011

Synchronized ListView objects (or how to scroll 2 ListView objects together)

In my previous post I have described how to synchronize two ListBox objects. Here I will show, how to synchronize two ListView objects.

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;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            this.listView1.View = View.Details;
            this.listView2.View = View.Details;
            for (int j = 0; j < 10; j++)
            {
                this.listView1.Columns.Add("c" + j.ToString());
                this.listView2.Columns.Add("c" + j.ToString());
            }
            for (int j = 0; j < 300; j++)
            {
                ListViewItem item = new ListViewItem("item" + j.ToString());
                for (int k = 1; k < 10; k++)
                {
                    item.SubItems.Add("sub item" + k.ToString());
                }
                this.listView1.Items.Add(item);
                this.listView2.Items.Add(item.Clone() as ListViewItem);
            }

            this.listView1.Scroll += new ListViewEx.ScrollHandler(listView1_Scroll);
        }

        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

        private const int WM_HSCROLL = 0x114;
        private const int WM_VSCROLL = 0x115;
        private const int SBS_HORZ = 0;
        private const int SBS_VERT = 1;

        void listView1_Scroll(object sender, MyScrollEventArgs e)
        {
            ListViewEx listVw = sender as ListViewEx;

            Int16 hi = (Int16)((int)e.WParam >> 16);//position
            Int16 lo = (Int16)e.WParam;//scroll type

            if (e.Orientation == ScrollOrientation.VerticalScroll)
            {
                if (lo == 5) //SB_THUMBTRACK
                {
                    if (SetScrollPos(this.listView2.Handle, SBS_VERT, hi, true) != 0)
                    {
                        SendMessage(this.listView2.Handle, WM_VSCROLL,
                          (IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);
                    }
                }
                else
                {
                    SendMessage(this.listView2.Handle, WM_VSCROLL, e.WParam, IntPtr.Zero);
                }
            }
            if (e.Orientation == ScrollOrientation.HorizontalScroll)
            {
                if (lo == 5)//SB_THUMBTRACK
                {
                    SetScrollPos(this.listView2.Handle, SBS_HORZ, hi, true);
                    SendMessage(this.listView2.Handle, WM_HSCROLL,
                       (IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);
                }
                else
                {
                    SendMessage(this.listView2.Handle, WM_HSCROLL, e.WParam, IntPtr.Zero);
                }
            }
        }

    }

    public class ListViewEx : ListView
    {
        public delegate void ScrollHandler(object sender, MyScrollEventArgs e);
        public event ScrollHandler Scroll;
        public void OnScroll(MyScrollEventArgs e)
        {
            if (Scroll != null)
            {
                Scroll(this, e);
            }
        }

        private const int WM_HSCROLL = 0x114;
        private const int WM_VSCROLL = 0x115;

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_VSCROLL)
            {
                MyScrollEventArgs e = new MyScrollEventArgs();
                e.WParam = m.WParam;
                e.Orientation = ScrollOrientation.VerticalScroll;
                OnScroll(e);
            }
            if (m.Msg == WM_HSCROLL)
            {
                MyScrollEventArgs e = new MyScrollEventArgs();
                e.WParam = m.WParam;
                e.Orientation = ScrollOrientation.HorizontalScroll;
                OnScroll(e);
            }
            base.WndProc(ref m);
        }
    }

    public class MyScrollEventArgs : EventArgs
    {
        private ScrollOrientation orientation;
        private IntPtr wParam;

        public IntPtr WParam
        {
            get { return wParam; }
            set { wParam = value; }
        }

        public ScrollOrientation Orientation
        {
            get { return orientation; }
            set { orientation = value; }
        }
    }
}

Synchronized ListBox objects (or how to scroll 2 ListBox objects together)

Before couple of days I had a task where I must synchronize two ListBox objects. I have fount out, that ListBox object doesn't have any property which allow to accomplish this. After a few hours of googling I found code of class that inherited from ListBox class. Here is the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace SyncLists
{
    class SyncListBox : System.Windows.Forms.ListBox
    {
        [Category("Action")]

        private const int WM_HSCROLL = 0x114;
        private const int WM_VSCROLL = 0x115;

        public event ScrollEventHandler OnHorizontalScroll;
        public event ScrollEventHandler OnVerticalScroll;


        private const int SB_LINEUP = 0;
        private const int SB_LINELEFT = 0;
        private const int SB_LINEDOWN = 1;
        private const int SB_LINERIGHT = 1;
        private const int SB_PAGEUP = 2;
        private const int SB_PAGELEFT = 2;
        private const int SB_PAGEDOWN = 3;
        private const int SB_PAGERIGHT = 3;
        private const int SB_THUMBPOSITION = 4;
        private const int SB_THUMBTRACK = 5;
        private const int SB_PAGETOP = 6;
        private const int SB_LEFT = 6;
        private const int SB_PAGEBOTTOM = 7;
        private const int SB_RIGHT = 7;
        private const int SB_ENDSCROLL = 8;

        private const int SIF_TRACKPOS = 0x10;
        private const int SIF_RANGE = 0x1;
        private const int SIF_POS = 0x4;
        private const int SIF_PAGE = 0x2;
        private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetScrollInfo(
        IntPtr hWnd, int n, ref ScrollInfoStruct lpScrollInfo);


        private struct ScrollInfoStruct
        {
            public int cbSize;
            public int fMask;
            public int nMin;
            public int nMax;
            public int nPage;
            public int nPos;
            public int nTrackPos;
        }

        protected override void WndProc(ref System.Windows.Forms.Message msg)
        {
            if (msg.Msg == WM_HSCROLL)
            {
                if (OnHorizontalScroll != null)
                {
                    ScrollInfoStruct si = new ScrollInfoStruct();
                    si.fMask = SIF_ALL;
                    si.cbSize = Marshal.SizeOf(si);
                    GetScrollInfo(msg.HWnd, 0, ref si);

                    if (msg.WParam.ToInt32() == SB_ENDSCROLL)
                    {
                        ScrollEventArgs sargs = new ScrollEventArgs(
                        ScrollEventType.EndScroll,
                        si.nPos);
                        OnHorizontalScroll(this, sargs);
                    }
                }
            }
            if (msg.Msg == WM_VSCROLL)
            {
                if (OnVerticalScroll != null)
                {
                    ScrollInfoStruct si = new ScrollInfoStruct();
                    si.fMask = SIF_ALL;
                    si.cbSize = Marshal.SizeOf(si);
                    GetScrollInfo(msg.HWnd, 0, ref si);

                    if (msg.WParam.ToInt32() == SB_ENDSCROLL)
                    {
                        ScrollEventArgs sargs = new ScrollEventArgs(
                        ScrollEventType.EndScroll,
                        si.nPos);
                        OnVerticalScroll(this, sargs);
                    }
                }
            }
            base.WndProc(ref msg);
        }


        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // scrolled
            // 
            this.Size = new System.Drawing.Size(120, 95);
            this.ResumeLayout(false);
        }
    }
}

add two SyncListBox objects on the form and add following code:

private void syncListView2_OnVerticalScroll(object sender, ScrollEventArgs e)
{
    syncListView1.TopIndex = syncListView2.TopIndex;
}

private void syncListView1_OnVerticalScroll(object sender, ScrollEventArgs e)
{
    syncListView2.TopIndex = syncListView1.TopIndex;
}

Sunday, November 14, 2010

Calling JavaScript function from WinForms and vice-versa



I'be been working on application that needs to load page and display it in WebBrowser control. Second requirement was to allow interaction between WinForms application and web page. After a couple of minutes of googling I found some important information that helped me to solve my problem. Here I will show a sample application where JavaScript function is called from WinForms application.

Hole process can be described by following steps:
  • Create Windows Forms application
  • Add WebBrowser control into Form
  • Create web page with JavaScript function you want to call

Calling JavaScript function from WinForms application isn't so difficult. WebBrowser constrol has property Document which gets an HtmlDocument representing the Web page currently displayed in the WebBrowser control.

You can use this property, in combination with the ObjectForScripting property, to implement two-way communication between a Web page displayed in the WebBrowser control and your application. Use the HtmlDocument.InvokeScript method to call script methods implemented in a Web page from your client application code. Your scripting code can access your application through the window.external object, which is a built-in DOM object provided for host access, and which maps to an object that you specify for the ObjectForScripting property.

<html>
     <head>
          <title></title>
          <script type="text/javascript">        

          function ShowMessage(message)
          {
               alert(message);
          }
        
          function ShowWinFormsMessage() {
               var msg = document.getElementById('txtMessage').value;
               return window.external.ShowMessage(msg);
          }
        
          </script>
     </head>  
     <body>
          <input type="text" id="txtMessage" />
          <input type="button" value="Show Message" onclick="ShowWinFormsMessage()" />
     </body>
</html>

Two JavaScript functions are in sample page. function ShowMessage(message) is called from WinForms application and function ShowWinFormsMessage call ShowMessage(msg) C# function.




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;

namespace WebBrowserJavaScriptExample
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
            webBrowser1.ObjectForScripting = new ScriptManager(this);
        }

        private void btnShowMessage_Click(object sender, EventArgs e)
        {
            object[] o = new object[1];
            o[0]=txtMessage.Text;
            object result = this.webBrowser1.Document.InvokeScript("ShowMessage", o);
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            this.webBrowser1.Navigate(@"E:\Projects\2010\WebBrowserJavaScriptExample\WebBrowserJavaScriptExample\TestPage.htm");
        }

        [ComVisible(true)]
        public class ScriptManager
        {
            frmMain _form;
            public ScriptManager(frmMain form)
            {
                _form = form;
            }

            public void ShowMessage(object obj)
            {
                MessageBox.Show(obj.ToString());
            }
        }
    }
}

More information about WebBrowser object ju can find here:

http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.document.aspx