2010年3月29日 星期一

20100327 GARMIN 北宜之旅

中途休息站,坪林陳德利茶莊,我與 Partner
陳德利茶莊

北宜公路最高點
北宜最高點
北宜最高點

鳥瞰蘭陽平原
眺望蘭陽平原

礁溪火車站月台
礁溪火車站月台

兩鐵專車
兩鐵專車

2010年3月25日 星期四

MusicCopy

中文版

April 6, 2010 MusicCopy 0.6.1 Released Download

This is bug-fix release.
Fixed:
  • Prefix error
  • Parse mp3 tag information error


April 2, 2010 MusicCopy 0.6 Released Download

New function:

  • About
  • Display the version of the program and the release date.

  • Move & Sort
  • You coulld select one or many MP3s and then click the move button. It will change the sequece of the list. "Sort" function enabled when the files contain ID3v1 tag information. It is based on the same album and then sort by the track.

  • Display
  • It will display "Performer-Title" based on ID3v1 tag. If the file didn't have ID3v1 tag, show the filename instead.





"MusicCopy" is a small software to copy music files(MP3, WMA) from computer to the USB device.

OS: Windows XP Above (Tested on WinXP, Vista 32 bit, Win7 64 bit)
Library: .Net Framework 3.5 SP1 (Download) Note! Install this before excute.
Program: Download from here. Extract and double-click MusicCopy.exe



  • Tool Bar


    • Copy



      1. Target Folder
      2. Type the folder name in the text field, or click the folder icon to select. If the folder is not existed, it will create automatically. Note, if you choose the folder which is not under the removable device, it will raise an exception.
      3. Option
      4. The 3rd option will keep the sequence of song list.
      5. Start and Stop
      6. Click "Start" button to start, and then "Stop" button appeared.

    • Device List


      1. This window will display all removable devices in this computer. You could see the basic information of the device, including the drive label, size, available size and the file system. Select the target device which to be copied.

    • About


      1. Introduce the purpose of this software.


  • Header Information

  • Display the selected device.

  • Song List
  • Display the whole songs. You could add songs through the command bar or drag-and-drop from your folders or files. If you add from a folder, it will add all *.mp3 and *.wma files in this folder and sub-folders.

  • Command Bar

  • Add single file, add a folder and delete files.


  • Status

  • Display the total size in the song list and the free space of the target device. If the size of song list is bigger than device size, the color will convert to red.

2010年3月22日 星期一

汐止 ←→ 冷水坑 (小 3P)

去程:汐止國泰醫院→汐萬路→五指山涼亭→風櫃嘴→楓林橋→至善路→至善路71巷平菁街菁山路菁山路101巷→冷水坑遊客服務站

回程:冷水坑遊客服務站→菁山路101巷→菁山路→平菁街→至善路71巷→至善路→楓林橋→風櫃嘴→五指山涼亭→汐萬路→汐止國泰醫院

總里程:78.41KM
總騎乘時間:5:48:39

行程圖片





2009年12月17日 星期四

LINQ and Deploying SQL Server CE 3.5

I have to use INNO Setup to deploy my WPF desktop application with LINQ and SSCE.

On my development desktop, everything is fine. But when I installed the package on another VMs(Win7 and WinXP), it crashed. Then I checked the exception and figured out the reason is connecting DB error. I compared the environment between my development desktop and the VMs. The suspect is Microsoft SQL Server Compact 3.5 SP1 English. It means that I need the runtime of SSCE.

I have 2 choices to solve this problem. One is to install SSCERuntime-ENU-x86.msi during the installation, and the other is to put necessary drivers with AP.

  • Install SSCE runtime during setup

  • In xxx.iss(Inno Setup Script) file, add belows:

    [Files]
    Source: SSCERuntime-ENU-x86.msi; DestDir: {tmp}; Flags: deleteafterinstall

    Besides, we need to add some codes. First, check if SSCE installed.

    RegKeyExists(HKLM, 'Software\Microsoft\Microsoft SQL Server Compact Edition\v3.5');

    If not installed, execute the SSCERuntime-ENU-x86.msi.

    ExtractTemporaryFile('SSCERuntime-ENU-x86.msi');
    Exec('msiexec',ExpandConstant('/i "{tmp}\SSCERuntime-ENU-x86.msi" /qb'),'', SW_SHOW, ewWaitUntilTerminated, ResultCode);

  • Prepare the necessary SSCE drivers

  • Actually, I preper this solution.
    I read "LINQ and Deploying SQL Server CE 3.5" by Matt Sollars on CodeProject and tried so many times, but it didn't work. So if you guys read that article and everything is fine and you could jump this section.

    Besides the 7 dlls that Matt Sollars suggested, I add "System.Data.SqlServerCe.Entity.dll".
    In application config, check the version of System.Data.SqlServerCe
    SSCE_3_5_1
    So, my App.config is:

    <configuration>
    <system.data>
    <DbProviderFactories>
    <remove invariant="System.Data.SqlServerCe.3.5" />
    <add name="Microsoft SQL Server Compact Data Provider"
    invariant="System.Data.SqlServerCe.3.5"
    description=".NET Framework Data Provider for Microsoft SQL Server Compact"
    type="System.Data.SqlServerCe.SqlCeProviderFactory,
    System.Data.SqlServerCe,
    Version=3.5.1.0,
    Culture=neutral,
    PublicKeyToken=89845dcd8080cc91"/>
    </DbProviderFactories>
    </system.data>
    </configuration>

    Finally, don't forget to copy XXX.exe.config to the installation directory.

2009年11月30日 星期一

Exercises : C++ How to Program, Fifth Edition

Developement Environment: Dev-C++ 4.9.9.2


  • 3.11

  • (Modifying Class GradeBook) Modify class GradeBook (Figs. 3.113.12) as follows:
    a. Include a second string data member that represents the course instructor's name.
    b. Provide a set function to change the instructor's name and a get function to retrieve it.
    c. Modify the constructor to specify two parametersone for the course name and one for the instructor's name.
    d. Modify member function displayMessage such that it first outputs the welcome message and course name, then outputs "This course is presented by: " followed by the instructor's name.
    Use your modified class in a test program that demonstrates the class's new capabilities.

    • GradeBook.h


    • #include
      using std::string;

      class GradeBook
      {
      public:
      GradeBook(string, string);
      void setCourseName(string);
      string getCourseName();
      void setCourseInstructorName(string);
      string getCourseInstructorName();
      void displayMessage();

      private:
      string courseName;
      string courseInstructorName;
      };

    • GradeBook.cpp


    • #include
      using std::cout;
      using std::endl;

      #include "GradeBook.h"

      GradeBook::GradeBook(string name, string insName)
      {
      setCourseName(name);
      setCourseInstructorName(insName);
      }

      void GradeBook::setCourseName(string name)
      {
      courseName = name;
      }

      string GradeBook::getCourseName()
      {
      return courseName;
      }

      void GradeBook::setCourseInstructorName(string insName)
      {
      courseInstructorName = insName;
      }

      string GradeBook::getCourseInstructorName()
      {
      return courseInstructorName;
      }

      void GradeBook::displayMessage()
      {
      cout << "Welcome to the grade book for\n" << getCourseName() << "!" <<
      "\nThis course is presented by:" << getCourseInstructorName()
      << endl;
      }

    • main.cpp


    • #include
      using std::cout;
      using std::endl;

      #include "GradeBook.h"

      int main(int argc, char *argv[])
      {
      GradeBook gradeBook1("CS101 Instroduction to C++ Programming", "John");

      gradeBook1.displayMessage();

      system("PAUSE");
      return EXIT_SUCCESS;
      }

    • Output


    • Download Source from here.

  • 3.12

  • (Account Class) Create a class called Account that a bank might use to represent customers' bank accounts. Your class should include one data member of type int to represent the account balance. [Note: In subsequent chapters, we'll use numbers that contain decimal points (e.g., 2.75)called floating-point valuesto represent dollar amounts.] Your class should provide a constructor that receives an initial balance and uses it to initialize the data member. The constructor should validate the initial balance to ensure that it is greater than or equal to 0. If not, the balance should be set to 0 and the constructor should display an error message, indicating that the initial balance was invalid. The class should provide three member functions. Member function credit should add an amount to the current balance. Member function debit should withdraw money from the Account and should ensure that the debit amount does not exceed the Account's balance. If it does, the balance should be left unchanged and the function should print a message indicating "Debit amount exceeded account balance." Member function getBalance should return the current balance. Create a program that creates two Account objects and tests the member functions of class Account.

    • Account.h


    • #include
      using std::string;

      class Account
      {
      public:
      Account(int);
      void credit(int);
      void debit(int);
      int getBalance();

      private:
      int balance;
      };

    • Account.cpp


    • #include
      using std::cout;
      using std::endl;

      #include "Account.h"

      Account::Account(int initAmount)
      {
      if(initAmount < 0)
      {
      balance = 0;
      cout << "ERROR!!! The initial balance was invalid.\n";
      }
      else
      balance = initAmount;

      }

      void Account::credit(int amount)
      {
      balance += amount;
      }

      void Account::debit(int amount)
      {
      if(amount > balance)
      {
      cout << "ERROR!!! Debit amount exceeded account balance.\n";
      return;
      }
      balance -= amount;
      }

      int Account::getBalance()
      {
      return balance;
      }

    • main.cpp


    • #include
      using std::cout;
      using std::endl;

      #include "Account.h"

      int main(int argc, char *argv[])
      {
      Account acct1(-10);
      cout << "Acct 1, Balance => $" << acct1.getBalance() << "\n";
      acct1.credit(100);
      cout << "Acct 1, Balance => $" << acct1.getBalance() << "\n";


      Account acct2(1000);
      cout << "Acct 2, Balance => $" << acct2.getBalance() << "\n";
      acct2.debit(2000);
      cout << "Acct 2, Balance => $" << acct2.getBalance() << "\n";

      system("PAUSE");
      return EXIT_SUCCESS;
      }

    • Output


    • Download source from here.

  • 9.6

  • (Rational Class) Create a class called Rational for performing arithmetic with fractions. Write a program to test your class.
    Use integer variables to represent the private data of the classthe numerator and the denominator. Provide a constructor that enables an object of this class to be initialized when it is declared. The constructor should contain default values in case no initializers are provided and should store the fraction in reduced form. For example, the fraction

    would be stored in the object as 1 in the numerator and 2 in the denominator. Provide public member functions that perform each of the following tasks:

    a. Adding two Rational numbers. The result should be stored in reduced form.
    b. Subtracting two Rational numbers. The result should be stored in reduced form.
    c. Multiplying two Rational numbers. The result should be stored in reduced form.
    d. Dividing two Rational numbers. The result should be stored in reduced form.
    e. Printing Rational numbers in the form a/b, where a is the numerator and b is the denominator.
    f. Printing Rational numbers in floating-point format.

    • TBD


2009年11月27日 星期五

WPF DataGrid

1. Create a WPF Application through Visual Studio 2008 SP1 and Dot Net Framework 3.5 SP1.

In Windows1.xaml

< Window x:Class="WpfDataGrid.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Window1" Height="300" Width="600">




< dg:DataGridTextColumn Header="First Name" Binding="{Binding Path=FirstName}"/>
< dg:DataGridTextColumn Header="Last Name" Binding="{Binding Path=LastName}"/>
< dg:DataGridTextColumn Header="Address" Binding="{Binding Path=Address}"/>
< dg:DataGridCheckBoxColumn Header="New?" Binding="{Binding Path=IsNew}"/>
< dg:DataGridCheckBoxColumn Header="Subscribed?" Binding="{Binding Path=IsSubscribed}"/>







In Windows1.xaml.cs
First, define a class to generate data to display.

public class Customer
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Address { get; set; }
public Boolean IsNew { get; set; }

// A null value for IsSubscribed can indicate
// "no preference" or "no response".
public Boolean? IsSubscribed { get; set; }

public Customer(String firstName, String lastName,
String address, Boolean isNew, Boolean? isSubscribed)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Address = address;
this.IsNew = isNew;
this.IsSubscribed = isSubscribed;
}

public static ObservableCollection GetSampleCustomerList()
{
return new ObservableCollection (new Customer[4] {
new Customer("A.", "Zero",
"12 North Third Street, Apartment 45",
false, true),
new Customer("B.", "One",
"34 West Fifth Street, Apartment 67",
false, false),
new Customer("C.", "Two",
"56 East Seventh Street, Apartment 89",
true, null),
new Customer("D.", "Three",
"78 South Ninth Street, Apartment 10",
true, true)
});
}
}


By this way, we could see the simple WPF DataGrid.


Run this program, one problem occured. If you would like to change the status of the checkbox, you have to click twice. First click will focus on the row, and second click will change the state of the checkbox.
The solution is to use DataGridTemplateColumn to replace the DataGridCheckBoxColumn.

















At this moment, everything seems to be ok. But in practice, if we could not make sure how many columns we have, what should we do?
So we need to create DataGrid programmatically.

In Windows1.xaml, we don't need the defination of the columns, just leave the declaration of < dg:DataGrid/>.

< Window x:Class="WpfDataGrid.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Window1" Height="300" Width="600">


< dg:DataGrid AutoGenerateColumns="False" Margin="22,24,20,26" Name="dataGrid"/>





In Windows.xaml.cs, I wrote a method InitDataGrid and put it after InitializeComponent().

private void InitDataGrid()
{
dataGrid.ItemsSource = Customer.GetSampleCustomerList();

dataGrid.Columns.Clear();

dataGrid.Columns.Add(GetTextColumn("First Name", "FirstName"));
dataGrid.Columns.Add(GetTextColumn("Last Name", "LastName"));
dataGrid.Columns.Add(GetTextColumn("Address", "Address"));
dataGrid.Columns.Add(GetCheckBoxColumn("New?", "IsNew"));
dataGrid.Columns.Add(GetCheckBoxColumn("Subscribed?", "IsSubscribed"));
}


private DataGridTextColumn GetTextColumn(string _header, string _binding)
{
DataGridTextColumn col = new DataGridTextColumn();
col.Header = _header;
if (_binding != null && _binding != "")
col.Binding = GetBinding(_binding, BindingMode.OneWay);
return col;
}


private DataGridTemplateColumn GetCheckBoxColumn(string _header, string _binding)
{
DataGridTemplateColumn col = new DataGridTemplateColumn();
col.Header = _header;

Dictionary values = new Dictionary();
//values.Add(CheckBox.StyleProperty, FindResource("DataGridCheckBoxStyle"));

Dictionary bindings = new Dictionary();
bindings.Add(CheckBox.IsCheckedProperty, GetBinding(_binding, BindingMode.TwoWay));

col.CellTemplate = GetDataTemplate(typeof(CheckBox), values, bindings);
return col;
}


private DataTemplate GetDataTemplate(Type _t, Dictionary _values,
Dictionary _bindings)
{
DataTemplate dt = new DataTemplate();
FrameworkElementFactory factory = new FrameworkElementFactory(_t);
dt.VisualTree = factory;
//SetValue
foreach (KeyValuePair kvp in _values)
{
factory.SetValue(kvp.Key, kvp.Value);
}
//SetBinding
foreach (KeyValuePair kvp in _bindings)
{
factory.SetBinding(kvp.Key, kvp.Value);
}
return dt;
}


private Binding GetBinding(string _path, BindingMode _mode)
{
Binding binding = new Binding();
binding.Path = new PropertyPath(_path);
binding.Mode = _mode;
return binding;
}


You could download the solution from here.
If you use Firefox, you may see strange syntax. If so, try to use IE or just download the source code.