Hey, wake up, men…

08/04/2009

Such a lo0Ooong time since the last post and today i return to this place to wake up my buddy….

Actually, i’m pretty busy these days. Hopefully, in one day, i can talk about the things make me crazy in this time. But for this entry, let me show u an interesting video clip, I really like it ;)


Easily way to make transparent picture control in MFC

28/01/2009

I’m going to describe the way to make a transparent picture box control in MFC (Smart Device application). It worked well on Windows CE, and it should be fine on Win32 application.

The key function is TransparentImage. Using it, you will see that the job is pretty simple…

Read the rest of this entry »


Sending SMS message in Windows CE

15/01/2009

Download the source code

Today I will show the way to send SMS message in Windows CE and Windows Mobile, using C++ and P/Invoke in .NET CF. It’s pretty simple…

In Windows CE environment, SMS fuction is handled by “sms.dll”, but in Windows Mobile 2005 and later, it’s handled (in a much more simpler way) by “cemapi.dll”. The “cemapi.dll” is not documented very well, in the other hand, you can find lots of information about “sms.dll” on MSDN.

Read the rest of this entry »


Scrolling PropertyPage in MFC

26/11/2008

My code to make a scrolling propertyPage in MFC, super easy to use…

Read the rest of this entry »


Some stuff with media in WM

25/10/2008

Trong namespace Microsoft.WindowsMobile.Forms có các lớp sau:

- CameraCaptureDialog

- SelectPictureDialog

- ChooseContactDialog

Vẫn đang tìm cách làm việc tương tự trong native code.

Update: Hình như WinCE có API SHCameraCapture, GetOpenFileNameEx… j j đó. Xong cái này!


Ensure reading data from socket in .NET

18/10/2008
private void ReadSockData(Socket sock, int len, byte[] dest)
{
  int iByteRead = 0;
  while (iByteRead < len)
  {
    iByteRead += sock.Receive(dest, iByteRead, len - iByteRead,
SocketFlags.None);
  }
}

How to programmatically establish GPRS connection in .NET CF

08/10/2008

This is a simple way to establish GPRS connection in .NET CF using RAPI. Remember to check “Allow unsafe Code Blocks” option in project properties page!
Read the rest of this entry »


Another trick with System.Net.Sockets.NetworkStream class

04/10/2008

Để hiểu dc cái trick này, người viết đã phải mất vài ngày… Hix…

Bình thường thì một ứng dụng mạng .NET sẽ có thread mạng được bọc trong vòng lặp như sau:

NetworkStream s = m_TcpClnt.GetStream();
while (s.DataAvailable)
{
//read mess
s.Read(aLen, 0, MSG_LEN);
// ……………
}

Ở đây ta dùng thuộc tính DataAvailable của lớp NetworkStream để xác định khi nào trong stream còn dữ liệu. Tuy nhiên vấn đề là nếu ta vừa đọc lên 1 lượng dữ liệu khá lớn (tầm 2KB) trong vòng while thì ngay sau đó, mặc dù phía server ko truyền gì nữa, nhưng DataAvaiible vẫn có giá trị TRUE, và vòng lặp tiếp tục, ta sẽ đọc được toàn là rác…

Để hạn chế điều này, ta có thể viết như sau:

while(true)

{

NetworkStream s = m_TcpClnt.GetStream();
if(s.Read(aLen, 0, MSG_LEN) > 0)
{
// ……………
}

}

Hàm Read() sẽ block đến khi nào có dữ liệu mới thoát, trả về số byte mà nó nhận được. Mặc dù không triệt tiêu 100% (nhất là khi truyền qua môi trường WiFi, GPRS v.v…) nhưng có lẽ đây cũng là cách hiệu quả.


Non-fullscreen form in Windows CE

28/09/2008

By default, all of form you created in .NET CF for Pocket PC and Smartphone are full screen. I don’t know why but this seem there are something related to MS rules when they design the OS. But in some application, I do want to make some non-fullscreen form (I mean the “floating form”) in .NET CF. And I found out it’s pretty simple. In this post, I will show the way to do it in .NET CF. ’cause I only use WinCE API, you can archive this in Native projects in even simpler way…

Read the rest of this entry »


Mouse Events for WebBrowser control in .NET CF

13/07/2008

This is my first contribution on codeproject. So shy… If you like it, feel free to comment and… vote here.

Introduction

Nearly, in one of my .NET Compact Framework 2.0 projects, I want to use the WebBrowser Control to display rich-media content. Unfortunately, the WebBrowser control in the .NET CF is not as powerful as the .NET Framework’s control. It does not have some of useful interfaces, especially it does not support DOM model… My requirements for the control are:

  • Doesn’t have the progress bar at the bottom.
  • Doesn’t use the defaut context menu. (disable it, or even better, I can customize the context menu)
  • Has a way to append HTML text into it (DocumentText or something like that).
  • Can handle Mouse events (MouseUp, MouseDown, MouseMove).

The OpenNETCF’s SDF WebBrowser control does satisfy first three requirements, but it still can not handle mouse events. So I decided to expand the standard WebBrowser control so that it can play with mouse events.

Background

In the .NET Framework, using the Document property, we can easily handle mouse events for the WebBrowser control; but the .NET CF doesn’t. Because when user click on the WebBrowser control, he actually click on the Document that the control hosts, so the WebBrowser does not know this event, and of course it doesn’t raise the correlative events.

The idea to solve the problem: derive the WebBrowser control, and hook all of mouse events which occur inside the control. Thanks to OpenNETCF’s ApplicationEx class, we can achieve this in managed code. Concretely, we write a class called WebBrowserEx, which is derived from .NET CF’s WebBrowser control, and implemented the IMessageFilter interface. This interface will help us to hook and catch WM_LBUTTONUP, WM_LBUTTONDOWN and WM_MOUSEMOVE meassage. (If you haven’t been farmiliar with IMessageFiter, you should go to the OpenNETCF’s website and have a look).

But, when click on the WebBrowser, which is the child window receive these messages? Not a problem! Using the Remote Spy utility (in the Visual Studio Remote Tools), we can see a grandchild window of the WebBrowser control. This window belongs to PIEHTML class and receives all of mouse messages.

Remotespy.jpg

Implementation

There are only approximate 100 lines of code in the WebBrowserEx class, so I paste all here.

Collapse
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;
using OpenNETCF.Win32;
using Microsoft.WindowsCE.Forms;

namespace webBrowserEx
{
    /// <summary>
    /// An extended WebBrowser, can handle Mouse Events.
    /// </summary>
    public class WebBrowserEx : System.Windows.Forms.WebBrowser, IMessageFilter
    {

        public WebBrowserEx()
        {
            //Initialize Message Filter, using OpenNETCF's ApplicationEx
            OpenNETCF.Windows.Forms.ApplicationEx.AddMessageFilter(this);
        }

        #region ------ IMessageFilter implementation ------

        public bool PreFilterMessage(ref Message m)
        {
            if ((m.Msg == (int)WM.LBUTTONDOWN || m.Msg == (int)WM.LBUTTONUP || m.Msg == (int)WM.MOUSEMOVE)
                 && IsChildestWindow(this.Handle, m.HWnd))
            {
                int xPos = (int)m.LParam & 0xFFFF;
                int yPos = ((int)m.LParam >> 16) & 0xFFFF;

                MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1,
                                        xPos, yPos, 0);

                switch (m.Msg)
                {
                    case (int)WM.LBUTTONUP:
                        base.OnMouseUp(e);
                        break;
                    case (int)WM.LBUTTONDOWN:
                        base.OnMouseDown(e);
                        break;
                    case (int)WM.MOUSEMOVE:
                        base.OnMouseMove(e);
                        break;
                }
            }

            return false;
        }

        #endregion

        #region ------- Private functions -----------------

        /// <summary>
        /// Check whether <see cref="hCheck"/> is one of <see cref="hWnd"/>'s grandchildren.
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="hCheck"></param>
        /// <returns></returns>
        private static bool IsChildestWindow(IntPtr hWnd, IntPtr hCheck)
        {
            IntPtr ret = hWnd;

            //Find the first "smallest" child
            while ((hWnd = GetWindow(hWnd, (int)GetWindowFlags.GW_CHILD)) != IntPtr.Zero)
            {
                ret = hWnd;
            }

            //goes through all of "smallest" grandchildren
            hWnd = ret;
            while ((ret != hCheck) &&
                ((hWnd = GetWindow(ret, (int)GetWindowFlags.GW_HWNDNEXT)) != IntPtr.Zero))
            {
                ret = hWnd;
            }

            return (hWnd != IntPtr.Zero);
        }

        #endregion

        #region -------- P/Invoke declerations ------------

        /// <summary>
        /// Get relative window with a given window.
        /// </summary>
        /// <param name="hwnd">the Given window</param>
        /// <param name="cmd">an <see cref="GetWindowFlags"/> value, indicates the relation.</param>
        /// <returns></returns>
        [DllImport("coredll.dll")]
        private static extern IntPtr GetWindow(IntPtr hwnd, int cmd);

        private enum GetWindowFlags : int
        {
            GW_HWNDFIRST = 0,
            GW_HWNDLAST = 1,
            GW_HWNDNEXT = 2,
            GW_HWNDPREV = 3,
            GW_OWNER = 4,
            GW_CHILD = 5,
            GW_MAX = 5
        }

        #endregion
    }
}

The implementation is so easy. Whenever receiving a WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN message, we will check if the m.HWnd is a grandchild of the WebBrowser (i.e. the PIEHTML window) and raise the correlative events.

The last thing we have to do is use the OpenNETCF.Windows.Forms.ApplicationEx class to run the application, in stead of System.Windows.Forms.Application. This will help receiving and processing messages in the PreFilterMessage function. We place this code in Program.cs:

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
        static void Main()
        {

            // Instead of using Application class,
            // we use OpenNETCF's ApplicationEx which enables MessageFilter.
            OpenNETCF.Windows.Forms.ApplicationEx.Run(new Form1());
            //Application.Run(new Form1());
        }
    }

Points of Interest

  • I built the sample code in VS 2008, using Smart Device Project on .NET Compact Framework 2.0. But in .NET CF 3.5, it should be fine.
  • Instead of using System.Windows.Forms.WebBrowser, you can use the OpenNETCF.Windows.Forms.WebBrowser class. In that case, you only have to replace System.Windows.Forms.WebBrowser by OpenNETCF.Windows.Forms.WebBrowser
    /// <summary>
    /// An extended WebBrowser, can handle Mouse Events.
    /// </summary>
    public class WebBrowserEx : OpenNETCF.Windows.Forms.WebBrowser, IMessageFilter
    {
        //.... 
    }

    Derived from OpenNETCF’s WebBrowser, you can use WebBrowserEx in .NET CF 1.0, and it have built-in functions such as: disabled the default context menu, doesn’t have the progress bar…

Through the years, I learn a lot of interesting things from CodeProject, but this is my first article, with a shy code… So, feel free to comment and… ^^.

Sorry for my English, it’s not my mother language.