I was trying to setup my laptop with Ubuntu 10.10. Well, so far, most of applications and devices are working as expected. However, the microphone with Gmail Chat is pretty much a pain.


First of all, I found this link and installed the pavucontrol and changed the settings to Microphone 2. Well, it works with Skype but not with Gmail Chat. The Gmail Chat driver auto adjusts volume so it all went back to the default settings again... WTF...


Anyway... keep fighting on it at the moment... Has anyone had this problem and resolved it?
by Elvis Hsu No comments Read More

Well, this is long way back when I was a rookie to develop Windows Mobile applications with C#.
I believe there are some people want to sync the device date/time with their web server as the device date/time somehow doesn't tick correctly after certain days. So first of all, you should have a look the SetSystemTime function as you need a SYSTEMTIME structure to pass the value to SetSystemTime function.

We start to P/Invoke the SetSystemTime method.

[DllImport("coredll.dll", SetLastError = true)]
private static extern bool SetSystemTime(ref SYSTEMTIME time);

Create the SYSTEMTIME structure.

public struct SYSTEMTIME
{
     public short year;
     public short month;
     public short dayOfWeek;
     public short day;
     public short hour;
     public short minute;
     public short second;
     public short milliseconds;
}

Create a simple function to convert DateTime to SYSTEMTIME and also calls the SetSystemTime function.

public void SetSystemDateTime(DateTime time)
{
    SYSTEMTIME s = new SYSTEMTIME();
     s.Year = (short)time.Year;
     s.Month = (short)time.Month;
     s.DayOfWeek = (short)time.DayOfWeek;
     s.Day = (short)time.Day;
     s.Hour = (short)time.Hour;
     s.Minute = (short)time.Minute;
     s.Second = (short)time.Second;
     s.Milliseconds = (short)time.Millisecond;
     SetSystemTime(ref s);
}

As most http web pages contains "Date" part of the document header and the "Date" part usually is the server time. So we gets the date/time and sync with our device. We use HttpWebRequest and HttpWebResponse to get the web page header.

public bool SyncDateTime(string url)
{
    HttpWebRequest myRequest = null;
    HttpWebResponse myResponse = null;
    try
    {
        //create a HTTP request of the file and capture the response
        myRequest = (HttpWebRequest)WebRequest.Create(url);
        myRequest.Accept = "*/*";
        myRequest.KeepAlive = false;

        // Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.          
        myResponse = (HttpWebResponse)myRequest.GetResponse();

        if (myResponse != null)
        {
            if (myResponse.Headers["Date"] != null)
            {
                DateTime dt = DateTime.Parse(myResponse.Headers["Date"], CultureInfo.CurrentCulture);
                // Sets the parsed time to device.
                SetSystemDateTime(dt.ToUniversalTime());
                return true;
            }
        }
    }
    finally
    {
        // Releases the resources of the response.
        if (myResponse != null)
            myResponse.Close();

        myRequest = null;
        myResponse = null;
    }
    return false;
}

Above method has few millisecond or event seconds inaccuracy as we doesn't calculate the time difference from request to response. However, it is quite good enough for many customers. Ha... I am lazy again...
by Elvis Hsu No comments Read More
When I deploy the application to customers, I like to wrap all cabs in one as it would be much easier. For example, .NETCF and SQLCE. If the device is new, the .NETCF or SQLCE needs to be installed prior running my application. Thanks for CeSetupDriver and here. They helped me a lot to deploy the application with the way I want. However, I don't want to prompt user every time that the .NETCF or SQLCE has already installed. So I come up with a checking method to validate that the application has already installed and skip to next cab installation. All you need to do is passing you name of application and CSP (Configuration Service Provider) xml to validate. However, somehow I feel the code is a bit long. Can anyone shorten it? Ha... I am just lazy...

/** 
 * Query the installation files
 *
 * @param LPTSTR xmlDoc The xml document 
 * @param appName The application name
 * @return Returns true if installed
 */
BOOL Utils::QueryInstalledByCSP(LPTSTR xmlDoc, const TCHAR *appName)
{
  BOOL szResult = FALSE;
  
  if(xmlDoc == NULL)
   return FALSE;
   IXMLDOMDocument *pDOM = NULL;
    
    // Load the XML DOM
    if(SUCCEEDED(CoInitializeEx(NULL,COINIT_MULTITHREADED)))
 {    
  if(SUCCEEDED(CoCreateInstance(CLSID_DOMDocument, NULL, 
   CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 
   IID_IXMLDOMDocument, (LPVOID *) &pDOM)))
  {
   // Tell the "doc" that we're not going to load asynchronously.
   if (SUCCEEDED(pDOM->put_async(VARIANT_FALSE)))
   {
    VARIANT_BOOL vBool;
    pDOM->loadXML(xmlDoc,&vBool);
    if (vBool == VARIANT_TRUE)
    {
     IXMLDOMNode *pNode;
     if (SUCCEEDED(pDOM->selectSingleNode(_T("wap-provisioningdoc"), &pNode)))
          {   
      IXMLDOMNodeList *pNodeList;
      IXMLDOMNode *pNodeChild;
      IXMLDOMNode *pNodeValue;
      IXMLDOMNamedNodeMap *pXMLNamedNodeMap;
      if (SUCCEEDED(pNode->selectSingleNode(_T("characteristic"), &pNode)))
      {   
       if(SUCCEEDED(pNode->selectNodes(_T("characteristic"), &pNodeList)))
       {
        long length = 0;
        pNodeList->get_length(&length);
        if(length > 0)
        {
         HRESULT hr = pNodeList->nextNode(&pNodeChild);
         while(hr == S_OK)
         {         
          if(SUCCEEDED(pNodeChild->get_attributes(&pXMLNamedNodeMap)))
          {
           if(SUCCEEDED(pXMLNamedNodeMap->getNamedItem(_T("type"), &pNodeValue)))
           {
            VARIANT varNodeValue;
            if(SUCCEEDED(pNodeValue->get_nodeValue(&varNodeValue)))
            {
             if(lstrcmpi(varNodeValue.bstrVal, appName) == 0)
             {
              szResult = TRUE;
              break;
             }
            }
            pNodeValue->Release();
           }
          }
          hr = pNodeList->nextNode(&pNodeChild);
         }
         pXMLNamedNodeMap->Release();
        }
        pNodeList->Release();
       }
      }
           }
     pNode->Release();
     pNode = NULL;
    }
   }
   pDOM->Release();
   // release COM
   CoUninitialize();
  }
 }
  return szResult;
}

So now what you have to do is add another method to check name of the cabs.
So far, it works all fine on all Motorola (Symbol) devices.

/** 
 * Check the installed application name with related cab file 
 */
BOOL Utils::CheckCabInstalled(LPTSTR xmlDoc, const TCHAR *cabName)
{
 if(lstrcmpi(cabName, _T("NETCFv35.wm.armv4i.cab")) == 0)
  return QueryInstalledByCSP(xmlDoc, _T("Microsoft .NET CF 3.5"));
 else if(lstrcmpi(cabName, _T("NETCFv35.Messages.EN.wm.cab")) == 0)
  return QueryInstalledByCSP(xmlDoc, _T("Microsoft .NET CF 3.5 EN-String Resource"));
 else if(lstrcmpi(cabName, _T("sqlce.ppc.wce5.armv4i.CAB")) == 0)
  return QueryInstalledByCSP(xmlDoc, _T("SQLServerCompact 3.5 Core"));
 else if(lstrcmpi(cabName, _T("sqlce.repl.ppc.wce5.armv4i.CAB")) == 0)
  return QueryInstalledByCSP(xmlDoc, _T("SQLServerCompact 3.5 Repl"));
 else if(lstrcmpi(cabName, _T("sqlce.dev.ENU.ppc.wce5.armv4i.CAB")) == 0)
  return QueryInstalledByCSP(xmlDoc, _T("SQLServerCompact 3.5 Tools EN"));
 else 
  return FALSE;
}
by Elvis Hsu No comments Read More


It was a while ago to play the colours in .NETCF. The case was drawing darker or lighter colour when user clicks my custom design buttons. Well, I believe it would be much easier to change the colour by its original colour. So I came up with two methods to extend the existing System.Drawing.Color object. These two methods can be found similar over the Internet. So, I have to thank all the developers in the Internet...



public static Color GetColorDarker(this Color color, double factor)
{
    // The factor value value cannot be greater than 1 or smaller than 0.
    // Otherwise return the original colour
    if (factor < 0 || factor > 1)
        return color;

    int r = (int)(factor * color.R);
    int g = (int)(factor * color.G);
    int b = (int)(factor * color.B);
    return Color.FromArgb(r, g, b);
}


public static Color GetColorLighter(this Color color, double factor)
{
    // The factor value value cannot be greater than 1 or smaller than 0.
    // Otherwise return the original colour
    if (factor < 0 || factor > 1)
        return color;

    int r = (int)(factor * color.R + (1 - factor) * 255);
    int g = (int)(factor * color.G + (1 - factor) * 255);
    int b = (int)(factor * color.B + (1 - factor) * 255);
    return Color.FromArgb(r, g, b);
}
by Elvis Hsu No comments Read More
Today, I was trying to install the Android SDK to my laptop and got "JDK not found on Installing Android SDK"... Well, I was a bit confused as I have installed the latest JDK.

So, I decided to google it. Most of results are for 64bit OS but I use 32bit Windows 7. Well, then I pressed "Back" button and then pressed "Next" again in the initialization page. Ha... It allows me to install it then...

I believe the installer caches the previous data if you haven't installed the JDK. Well, good to know that is easy to fix this installation issue...
by Elvis Hsu No comments Read More

I just tried to write a function to validate URL address. Well, as usual, I've done some researches on Google and not many efficient and satisfy solutions. However, I've got a solution which is using Regex in C# to validate a URL and it seems a acceptable method to test the URL input.

public static bool IsValidUrl(this string url)
{
    string strRegex = "^(https?://)"
        + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" // user@
        + @"(([0-9]{1,3}\.){3}[0-9]{1,3}" // IP- 10.0.0.1
        + "|" // allows either IP or domain
        + @"([0-9a-z_!~*'()-]+\.)*" // tertiary domain(s)- www.
        + @"([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]" // second level domain
        + @"(\.[a-z]{2,6})?)" // first level domain- .com or .museum is optional
        + "(:[0-9]{1,5})?" // port number- :80
        + "((/?)|" // a slash isn't required if there is no file name
        + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";

    return new Regex(strRegex).IsMatch(url);
}
by Elvis Hsu No comments Read More


Today I was think how to optimize the drawing string method on my library... so far I worked out this... However I still couldn't workout how to really wrap long string within the sentence...

Any help?


public static string[] WrapString(this Graphics gx, Font font, string text, float maxWidth, bool wrap)
{
    // find if actual max text width is smaller than max width or maxWidth is smaller than zero or wrap is set to false
    if (gx.MeasureString(text, font).Width < maxWidth || maxWidth <= 0 || !wrap)
    {
        return text.Split(new char[] { '\n' });
    }

    int maxChars = (int)(maxWidth / (gx.MeasureString("ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789", font).Width / 37));
    //text = text.BreakLongString(maxChars);

    text = text.Replace(Environment.NewLine, "\n");
    text = text.Replace("\r", "");
    text = text.Replace("\t", " ");

    string[] words = text.Split(new char[] { ' ' });
    List lines = new List((int)(text.Length / maxChars));
    string currentLine = "";

    for (int i = 0; i < words.Length; i++)
    {
        // if the word is empty, then repace it to one space
        if (string.IsNullOrEmpty(words[i]))
            words[i] = " ";

        float currWidth = gx.MeasureString(currentLine + " " + words[i], font).Width;
        
        // check if the current width is greater than max length
        if (currWidth < maxWidth)
        {
            // if first entry, then put current line to the first word
            if ((lines.Count == 0) && string.IsNullOrEmpty(currentLine))
                currentLine = words[i];
            else
            {
                // if not, append each word to current line
                currentLine += " " + words[i];

                // check if the currentline has \n in there.
                string[] newLines = currentLine.Split('\n');
                // if it does, then add a new line
                if (newLines.Length > 1)
                {
                    // do not loop to last as it will be the new currentline
                    for (int j = 0; j < newLines.Length - 1; j++)
                        lines.Add(newLines[j]);

                    // the current line is the last line of the new lines
                    currentLine = newLines[newLines.Length - 1];
                }
            }
        }
        else
        {
            // if the currentline width is greater than max width
            // then add a new line to the list
            if (!string.IsNullOrEmpty(currentLine))
                lines.Add(currentLine);

            // make the current line to the last word
            currentLine = words[i];
        }
    }
    
    // if still has word, add it to the list
    if (!string.IsNullOrEmpty(currentLine))
        lines.Add(currentLine);

    return lines.ToArray();
}
by Elvis Hsu No comments Read More