2007年3月29日 星期四

Apollo 使用 Windows 的檔案視窗(HTML 版本)
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.30 建立

今天發現Mike Chambers[1]的文章談到 HTML 中使用 Apollo 功能,將上次寫的 Apollo 使用 Windows 的檔案視窗 改成HTML來測試看看。測試程式如下:

application.xml
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/apollo/application/1.0.M3"
appId="com.adobe.mesh.HTMLFileExample" version=".4">

<properties>
<name>Browse Example</name>
<description>Browse Example Description</description>
<publisher>Chui-Wen Chiu</publisher>
<copyright>http://chuiwenchiu.spaces.live.com</copyright>
</properties>
<!-- 定義啟始網頁 -->
<rootContent systemChrome="standard" transparent="false" visible="true">
fileexample.html
</rootContent>

</application>


flleexample.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Browse Example</title>
<script type="text/javascript" src="fileexample.js"></script>
</head>

<body onload="onLoad()" style ='background:#222222'>
<input type="button" value="Load" onClick="onLoadFileClick();"><br />
<input type="button" value="Save" onClick="onSaveFileClick();"><br />
</body>
</html>


fileexample.js
var apollo = window.runtime;

// 網頁載入完成後觸發該事件
function onLoad(){
// 設定應用程式視窗尺寸
window.resizeTo(400,300);
}


// 開啟檔案
function onSaveFileClick(){
// 取得 File Object,請起始位置為桌面
var f = apollo.flash.filesystem.File.desktopDirectory;

// 監聽選取事件
f.addEventListener(apollo.flash.events.Event.SELECT, onSaveFile);

// 開啟視窗
f.download(new apollo.flash.net.URLRequest("http://localhost/"), "Untitle.txt");
}

function onSaveFile(e){
var file = e.target;
// 只是用來選取檔案而非實際下載,所以直接 Cancel 下載
file.cancel();

// 回傳 "file://檔案完整路徑"
alert( file.url );

// 回傳檔案名稱
alert( file.name );
}

// 開啟檔案
function onLoadFileClick(){
// 取得 File Object,請起始位置為桌面
var f = apollo.flash.filesystem.File.desktopDirectory;

// 監聽選取事件
f.addEventListener(apollo.flash.events.Event.SELECT, onLoadFile);

// 開啟視窗
f.browse();
}

function onLoadFile(e){
var file = e.target;

// 回傳 "file://檔案完整路徑"
alert( file.url );

// 回傳檔案名稱
alert( file.name );

// 回傳檔案名稱
alert( file.name );
}



執行結果



參考資料:
Apollo 使用 Windows 的檔案視窗
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.29 建立

Apollo 提供的 File 類別可以使用原生的檔案對話視窗來選取檔案,簡單的說就是 File.browse 和 File.download 分別呼叫""和""。測試程式如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
title="Browse Example"
backgroundColor="0x222222">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.IndexChangedEvent;
import mx.events.DragEvent;
import mx.containers.Canvas;
import flash.filesystem.*;

private var file:File;
public function save():void {
// 設定起始目錄為桌面
file = File.desktopDirectory;
// 監聽選取檔案動作
file.addEventListener(Event.SELECT, onFileSave);
// 儲存檔案視窗
file.download(new URLRequest("http://localhost/"), "Untitle.txt");
}
public function onFileSave(e:Event):void {
// 只是用來選取檔案而非實際下載,所以直接 Cancel 下載
file.cancel();

// file.url 回傳 "file://檔案完整路徑"
mx.controls.Alert.show( file.url );

// 取得檔名
mx.controls.Alert.show(file.name);
}
public function load():void {
// 設定起始目錄為桌面
file = File.desktopDirectory;

// 監聽選取檔案動作
file.addEventListener(Event.SELECT, onFileLoad);
// 開啟檔案視窗
file.browse([new FileFilter("All Files", "*.*")]);
}
// 檔案選取的事件處理函數
private function onFileLoad(e:Event):void {
// file.url 回傳 "file://檔案完整路徑"
mx.controls.Alert.show( file.url );

}
]]>
</mx:Script>
<mx:VBox left="5" top="5" bottom="5" right="5" horizontalAlign="center">
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="Load..." click="load()" />
<mx:Button label="Save..." click="save()" />
</mx:HBox>
</mx:VBox>
</mx:ApolloApplication>

執行結果



參考資料:

2007年3月25日 星期日


演算法問題1-2:支配值數目
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

摘至 [1] 的問題 1-2,問題描述如下:
已知f[]與g[]兩個整數陣列,元素都已經至小到大排序好,請寫一個程式算出 f[] 中比 g[] 中元素大的對數。換句話說,f[0] 比 g[]中多少個元素來的大,f[1] 比 g[]中多少個元素來的大等等,這些值得總和就是我們要求答案。

舉個例子,如果 f[] 中有 1,3,5,7,9 而 g[] 中有 2,3,4,7,8。因此比 g[0] 大的有 f[1] 到[4],比g[1]大的有f[2]到f[4],比g[2]大的有f[2]到f[4],比g[3]大的有f[4],比g[4]大的有f[4],所以答案為 4+3+3+1+1 = 13。

我的解法-版本#1
#include <iostream>

template<int len1, int len2, typename T1, typename T2>
int gt_count(T1 f[], T2 g[]){
int count = 0;
int pos = 0;
for(int i = 0; i<len2; ++i){
for(int j = pos; j<len1; ++j){
if (g[i] < f[j]){
count += len1-j;
pos = j;
break;
}
}
}

return count;
}

int main(){
int f[] = {1, 3, 5, 7, 9};
int g[] = {2, 3, 4, 7, 8};

std::cout << gt_count<5, 5>(f, g) << std::endl;
return 0;
}

參考資料
[1] C 名題精選百則 技巧篇

演算法問題1-3:等值數目
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

摘至 [1] 的問題 1-3,問題描述如下:
以兩個整數陣列 f[] 與 g[],他們的元素經自小到大排列好,而且兩個陣列元素各自不相同;譬如說,f[] 中可能有 1,3, 4, 7, 9,而 f[] 有 3, 5, 7, 8, 10。請寫程式,算出這兩個陣列彼此之間有多少組相同資料。就以上例而言,f[2], g[1] 為3是第一組;f[4], g[3] 為8是第二組。

說明:
我並不期望你用下面的方式來寫作程式
a. 固定 f[i]
b. 對於 f[i] 而言,檢查 g[]中有沒有與 f[i] 相同的元素
c. 處理下一個 f[i],即 f[i+1]

因為 f[] 與 g[] 都以經由小到大排序好,你應該活用這一個很強的特性;好程式員絕對不會用上面的本拙方式寫程式的,因為做了太多無意義的事。
為什麼呢?因為 g[] 的元素都相異,對於 f[i] 而言,最多只會只找一個與他相同的元素,但在會壞的情況下,你得把 g[] 全部查完才曉得這一回事,如果 g[] 有 n 個元素,你得查 n 次,但是若在 f[] 中也有 n 個元素,所以你得把 g[] 查 n 遍,一共做了 n2 個比較才能找出結果。

請試試看能夠找出方法,把 f[] 與 g[] 各查一次就可以找到答案。請記住,活用 f[] 與 g[] 已經自小到大排序好的特性。

我的解法-版本#1

#include <iostream>

template<int len1, int len2, typename T>
int eq_count(T f[], T g[]){
int count = 0;
int i = 0;
int j = 0;
while(i < len1 && j < len2){
if (f[i] == g[j]){
++count;
i<len1-1?++i:++j;

continue;
}

if (f[i] < g[j]){
i<len1-1?++i:++j;
continue;
}

if (f[i] > g[j]){
j < len2-1?++j:++i;
}
}

return count;
}

int main(){
int f[] = {1, 3, 4, 7, 8, 9, 11, 99, 101};
int g[] = {1, 3, 5, 7, 8, 10};

std::cout << eq_count<9, 6>(f, g) << std::endl;
return 0;
}


參考資料
[1] C 名題精選百則 技巧篇
演算法問題1-4:支配值數目
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

摘至 [1] 的問題 1-4,問題描述如下:
已知兩個元素自小到大排好的陣列 x[] 與 y[],請寫一個程式算出兩個陣列元素彼此之間差的絕對值中最小的一個,這叫做陣列的距離。

說明:
如果 x[i] 與 y[j] 是兩個元素,那麼 | x[i]-y[i] | 就是兩個元素之間的距離,所有這些距離的極小值叫做陣列距離,好比說 x[] 有 1,3,5,7,9,y[]有2,6,8,那麼最短距離就是1,因為 x[0] 與 y[0], x[1] 與 y[0], x[2] 與 y[1], x[3] 與 y[1] 還有 x[4] 與 y[2] 的距離都是 1。

請注意,如果 x[] 與 y[] 各有 m 與 n 個元素,那麼元素之間的距離就一共有 m*n 個;事實上我們往往用不著計算那麼多值,你應該活用 x[] 與 y[] 已經排序好的特性,不要把所有的距離都算出來。

我的解法-版本#1
#include <iostream>
#include <cmath>

template<int f_len, int g_len, typename T>
int mindist(T f[], T g[]){
int diff = abs( f[0]-g[0] );
if (diff == 0 || ( f_len == g_len == 1)){
return 0;
}

int i = 0;
int j = 0;
while(true){
if (f[i]<=g[j]){
i<f_len-1?++i:++j;
}else{
j<g_len-1?++j:++i;
}


if (i >= f_len || j >= g_len){
break;
}

if (diff > abs(f[i]-g[j])) {
diff = abs(f[i]-g[j]);
if (diff == 0 ){
return 0;
}
}
}

return diff;
}

int main(){
//int f[] = {1, 3, 5, 7, 9};
//int g[] = {2, 6, 8};

int f[] = {1, 2, 3, 4, 5};
int g[] = {6, 7, 8};
std::cout << mindist<5, 3>(f, g) <<std::endl;
return 0;
}

參考資料
[1] C 名題精選百則 技巧篇

演算法問題1-1:最長平台
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

摘至 [1] 的問題 1-1,問題描述如下:
已知已經自小到大排序好的陣列,我們說這個陣列中的平台(plateau),就是連續的一串值相同的元素,並且這一串元素不能再延伸。好比說,在 1,2,2,3,3,3,4,5,5,6 中 1, 2-2, 3-3-3, 4, 5-5, 6 都是平台。請寫一個程式,接收一個陣列,把這個陣列中最常的平台找出來;再上面的例子就是3,這是由 3-3-3 造成的。

說明:
這個程式十分簡單,但是要寫的好卻很難,因此在寫程式時你心中應該要想到下面的幾點:
a. 使用的變數越少越好
b. 能否只把陣列的元素每一個都只查久得到結果?
c. 程式敘述也要越少越好

我的解法-版本#1
#include <iostream>
// 變數: 4個
// 陣列存取次數: 1次
template<int len, typename T>
int plateau(T f[]){
if (len <= 0){
return 0;
}

if (len == 1){
return 1;
}

int count = 1;
int max = 1;
int v = f[0];
for(int i = 1; i<len; ++i){
if (v == f[i]){
++count;
continue;
}

if (count >max ){
max = count;
}
v = f[i];
count = 1;
}

return max;
}

int main(){
int f[] = {1,2,2,3,3,3,4,5,5,6};
std::cout << plateau<10>(f) <<std::endl;
return 0;
}



參考資料
[1] C 名題精選百則 技巧篇
演算法問題1-5:等值首尾和
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

摘至 [1] 的問題 1-5,問題描述如下:
假設有一個陣列 x[],他有 n 個元素,每一個元素都大於零; 我們說 x[0]+x[1]+...+x[i] 是個前段和,而 x[j] + x[j+1]+...x[n-1]則是後段和。請血衣各城市,求出 x[] 中有多少組相同的前段和與後段和。

說明:
如果x[]的元素是 3, 6, 2, 1, 4, 5, 2,於是x[]的前段和有以下七個,亦即3, 9, 11, 12, 16, 21, 33;後段和則是 2, 7, 11, 12, 14, 20, 23 於是 11, 12, 23 這三對就是值相同的前段和與後段和,因為

11 = 3+6+2 = 2+5+4
12 = 3+6+2+1 = 2+5+4+1

至於 23 則是整個陣列元素的和,自然前段與後段的和一定相同。
當然,你的成視野可以用上面的方式把前段和與後段和算出來,再進行比較,不過我們卻希望您不要用這個方法,因為他要額外的記憶體。

我的解法-版本#1
#include <iostream>

template<int len, typename T>
int headtail(T f[]){
if (len <= 0){
return 0;
}

int count = 1; // 整個陣列的和一定相同
int i = 0;
int j = len-1;
int lv = f[i];
int rv = f[j];
while(i<len-1 && j > 0){ // 邊界值,兩側最後一個值不用測試,因為累加到最後一定相等
if (lv <= rv){
if (lv == rv){
++count;
}

if (i <len-1){
lv += f[++i];
}else{
rv += f[--j];
}
continue;
}


if (lv > rv){
if (j >1){
rv += f[--j];
}else{
lv += f[++i];
}
}
}

return count;
}

int main(){
int f[] = {3, 6, 2, 1, 4, 5, 2};
std::cout << headtail<7>(f) << std::endl;

return 0;
}


參考資料
[1] C 名題精選百則 技巧篇
Delphi For PHP 初探
Chui-Wen Chiu(Arick)
MSN SpaceGoogle DocGoogle Blog
2007.03.27

測試環境:
1. Windows XP Pro + SP2
2. Delphi For PHP 1.0
3. MySQL 3.23.58

  • Application 架構
    • <?php
      //Includes
      require_once("vcl/vcl.inc.php"); // VCL 底層實作函數庫
      use_unit("forms.inc.php"); // 應用程式基本架構:Application, Frame, Page, Window, ...
      use_unit("extctrls.inc.php"); // 延伸 VCL 控制項:Image, FlashObject, GroupBox, Timer, Shape, ....
      use_unit("stdctrls.inc.php"); // 標準 VCL 控制項:Button, CheckBox, Label, Edit, ListBox, ...

      //Class definition
      class Unit1 extends Page // 每一頁面都需要繼承 Page
      {
      }

      global $application; // 在 forms.inc.php 中產生

      global $Unit1;

      //Creates the form
      $Unit1=new Unit1($application); // 將自訂 Page 加入 Application

      //Read from resource file
      $Unit1->loadResource(__FILE__);// Page 讀取 UI 設定 XML 檔, unit.xml.php, 定義在 Component

      //Shows the form
      $Unit1->show(); // 顯示頁面內容,定義在 Control

      ?>
    • 類別階層
      • + Object (system.inc.php)
        + Persistent (classes.inc.php)
        + Component (classes.inc.php)
        + Control (controls.inc.php)
        | + FocusControl (controls.inc.php)
        | + ScrollingControl (controls.inc.php)
        | + CustomPage (controls.inc.php)
        | + Page (forms.inc.php)
        + Application (controls.inc.php)
  • 顯示資料庫
  • 使用 Data Explorer
    • 透過 UI 設定資料庫連線,如果連線成功將可看到資料庫的所有 Table
    • 將 Table 拉到 Form 上即可,自動產生 Database, Table, DataSource 和 DBGrid
  • 手動使用 Database, Query, Datasource. DBGrid 完成資料庫呈現
    • 基本上就是將上面方式改成手動設定,Query 取代 Table 元件,透過 Query 元件可以指定查詢條件

  • 在控制項事件中使用 Javascript
  • 透過 Delphi For PHP 開發環境的 Object Inspector | Javascript 設定對應的 Event Handler
  • 此時,Delphi For PHP 會在 *.xml.php 中產生對應的 <property> 如: <property name="jsOnClick">JSClick</property>
  • Code Editor 也會產生對應的區塊,如:
    function JSClick($sender, $params)
    {
    ?>
    //Add your javascript code here
    alert( document.getElementById('MyButton1').value);
    <?php
    }

  • 前端產生的結果如下:
    function JSClick(event)
    {
    var event = event || window.event;
    var params=null;
    //Add your javascript code here
    alert( document.getElementById('MyButton1').value);

    }
  • 補充:想要透過 Javascript 取得 VCL 元件,透過 document.getElementById 即可取得,Id 即 VCL 的 name。

  • 自訂 VCL假設元件檔案名稱為 unit1.inc.php, unit1.package.php)
    • 建立自訂元件
      1. 選擇 Component | New Component
2. Ancestor Type 選擇你要從那一個類別繼承
3. Classname 給予一個你的元件名稱
4. Palette Page 指定元件放置在那一個分類中
5. 將 *.inc.php 複製到 C:Program FilesCodeGearDelphi for PHP1.0vcl
6. *.package.php 可以隨意放置

      • 補充:預設 use_unit 會到 C:Program FilesCodeGearDelphi for PHP1.0vcl 搜尋指定的 *.inc.php。如果想要變更目錄,必須修改 unit1.package.php 的 registerComponents("Additional",array("MyButton"),"cwc/unit1.inc.php");,如此, use_unit 就會到 vcl/cwc 下尋找該元件。

    • 建立非視覺化元件
      • 繼承 Component 系列的元件,而不要繼承 Control 系列的元件即可。

    • 新增 Server 端事件
      function FireMyEvent(){
      // 呼叫 Server 端事件,定義在 Component
      $this->callEvent('onmyevent', array($this, 1, 2, 3));
      }

      // 宣告一個事件
      protected $_onmyevent = null;
      function getOnMyEvent() { return $this->_onmyevent; }
      function setOnMyEvent($value) { $this->_onmyevent = $value; }
      function defaultOnMyEvent() { return ""; }

    • 新增屬性
  • 將游標移到元件需要加入屬性程式片段的地方,選擇 "Edit | Add New Property "
  • 自行加入 getXXX, setXXX 對應的函數,VCL 會自動產生 XXX 屬性,如下: (此寫法可以讓屬性再屬性視窗中進行設定)
    class MyButton extends Button{
    protected $_v;
    function getXXX(){ return $this->_v;}
    function setXXX($v){ $this->_v = $v; };
    }
  • 屬性的類型
    • 簡單:數值、字串... 等,使用者能夠直接編輯的皆屬此類
    • 列舉:透過下拉選單選擇
    • 物件:表單上得另一個物件
    • 子屬性:一個物件的多個屬性,如:Font.Case, Font.Color, Font.Align, ...
    • 陣列:使用特定的編輯器

    • 加入訂定圖示
      • 準備一張 16x16 24BPP 的 BMP 圖檔
      • 將圖檔命名和元件名稱一樣,如:MyButton 類別對應的圖檔為 MyButton.bmp
      • 將圖檔案放置在 unit1.package.php 的 setIconPath() 所指定路徑
      • 安裝 package 即可看到該圖示

    • 新增多個元件到已經存在的 Package 中
      • 只需要在 unit1.package.php 多加幾行 registerComponents 即可,如下:
        registerComponents("Additional",array("MyButton"),"unit1.inc.php");
        registerComponents("Additional",array("ArickButton"),"unit2.inc.php");

      • 重新安裝 Package

    • 設定 Package 名稱
      • 修改 unit1.package.php 的 setPackageTitle("System VCL for PHP Components");

    • 新增/移除 Package
      • 使用 Component | Package

  • 國際化
    • Delphi For PHP 提供 Internationalization Wizard 來讓你對不同的國家自訂語系,且程式會依據國家的不同將轉換成自訂的語系。Internationalization Wizard 負責的工作有
      a. 收集專案中使用的檔案
      b. 選擇應用程式要針對哪些國家建立對應語系檔
      c. 掃描所有的原始檔並產生相對應的語系檔

      當完成
      Internationalization Wizard 的動作後,在專案的目錄下會產生 local 目錄,這個目錄包含各語系檔案。假如你希望元件能夠取用語系檔的文字,必須使用 gettext() 或 _() 取得語系對應文字,如:
      $this->Button=_("Localize this string");

  • 快速鍵
    • Ctrl+J 程式樣板列表
    • F5 新增/移除中斷點
    • F6/Shift+F6 往前/往後移動 Code Editor Tab
    • F9 啟用除錯器執行程式
    • Shift+F9 不啟用除錯器執行程式

已知缺點:
1. 採用類似 ASP.NET 的 Server-Side Control 概念,所有元件的 Event 處理都是 Form Submit 到 Server 端處理後在重新呈現新頁面。
2. 每一次畫面的呈現似乎都需要解析畫面配置的 XML
3. 每一次的元件修改都需要重新安裝 Package
4. 透過 DBGrid 顯示 Big5 的中文資料會亂碼



VS2003 開發 ASP.NET 1.1 常見問題
MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.26

最近工作上交接一個 vs2003 開發的 ASP.NET,這是我第一次真正的使用 ASP.NET,之前都是屬於書本上的學習,基本上沒有遇到什麼問題。這次的交接我遇到一些錯誤訊息,並將這些錯誤訊息的可能解法整理成如下,希望和我遇到相同問題的人可以獲得一些幫助:
1. VS2003 開啟既有的 ASP.NET 專案時,出現"Visual Studio .NET 偵測到指定的 Web 伺服器不是執行 ASP.NET 1.1版。你將無法執行 ASP.NET Web 應用程式"。
A: 可以嘗試開啟"Visual Studio .NET 2003 命令提示字元",並在命令模式下輸入 ASPNET_REGIIS -i 進行 ASP.NET 1.1 伺服器安裝。如果仍然無法解決問題,請參考這裡
2. VS2003 開啟既有的 ASP.NET 專案時,出現"Visual Studio .NET 無法建立或開啟應用程式。最可能的原因是本機Web伺服器上沒有安裝必要的元件。請執行 Visual Studio .NET 安裝程式並且加入 Web 開發元件"。
A: 確認專案目錄是否位於原來的路徑,且 IIS 是否有對應到該專案目錄的虛擬目錄,虛擬目錄名稱必須和專案名稱相同。如仍無法解決請參考這裡

3. 利用 VS2003 執行 ASP.NET 網頁時出現"嘗試執行專案時發生錯誤:無法在Web伺服器上啟動偵錯"
A: 嘗試修改 IIS 中將該網站的設定,"目錄安全性設定|匿名存取及驗證控制",勾選"匿名存取"和"整合式Windows驗證",若無法解決請參考
這裡


4. Build 專案時出現 "XXXXXlicenses.licx 無法將授權檔 'licenses.licx' 轉換為二進位資源。(1) : ....."
A: 將 licenses.licx 刪除重建 Build 即可。參考
這裡

2007年3月16日 星期五

[C#] 如何設定為全螢幕模式

MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.16 建立

要將視窗設定為全螢幕模式[1][5],主要有兩個部份
1. 視窗無框線
2. 視窗大小等於螢幕大小

在 .NET 的 Windows Form 中,只需要透過簡單的設定即可達到這個效果,
1. Form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; //設定成無框線[2]
2. Form.WindowState = FormWindowState.Maximized; // 視窗設定為最大化[3]

如果要設定更穩妥一點,可以再將視窗設定為最上層顯示,也就是將 Form.TopMost [4]設定為 true。
一般情況下,上述的作法就可以滿足,如果你想做的更好一些,將 Windows 工具列隱藏而非覆蓋[6],此時需要透過 Windows API 來達成,主要的概念是用 FindWindow 找尋工具列的視窗 Handle,再透過 ShowWindow 將該視窗 Handle 隱藏,C# 要實現這個機制的成片段如下

private const int SW_HIDE = 0;
private const int SW_SHOW = 1;

[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);

int hWnd = FindWindow("Shell_TrayWnd", "");
ShowWindow(hWnd, SW_HIDE);

理想上,上述已經算是相當的完美,但依據[5][6]的說法,即便是將工具列隱藏和 Form.WindowState = FormWindowState.Maximized 仍可能會使應用程式無法涵蓋整個螢幕,最後還是必須透過 Windows API 將 Windows 設定成和視窗一樣大小。先利用 GetSystemMetrics(SM_CYSCREEN) 和 GetSystemMetrics(SM_CXSCREEN) 分別取得螢幕的寬和高,最後再透過 SetWindowsPos 將視窗設定成和螢幕等寬並且置於上層
SetWindowPos(hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CYSCREEN), GetSystemMetrics(SM_CXSCREEN), SWP_SHOWWINDOW);

參考資料
[1] Full Screen Mode in C#
[2] Form.FormBorderStyle 屬性(System.Windows.Forms)
[3] Form.WindowState 屬性(System.Windows.Forms)
[4] Form.TopMost 屬性(System.Windows.Forms)
[5] Full Screen Video Display
[6] How to make Windows Form app truly Full Screen (and to hide Taskbar) in C#?
[7] How To Cover the Task Bar with a Window

2007年3月15日 星期四

[C#]使用 GZip 對 Stream 進行壓縮和解壓縮

MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.16 建立

.NET 2.0 支援 System.IO.Compression 名稱空間,其中定義了 GZipStream 類別[2]來壓縮和解壓縮 Stream 資料。GZipStream 繼承至 Stream 類別,所以該類別使用和一版的 Stream 類別相仿。下面是對一個外部檔案 Stream 進行壓縮和解壓縮的簡單範例:
using System;
using System.IO;
using System.IO.Compression;

namespace gzipTest {
class Program {
static void Main(string[] args) {
GZipTest.Compress("c:\vcredist_x86.exe", "c:\vcredist_x86.exe.zip");
GZipTest.Decompress("c:\vcredist_x86.exe.zip", "c:\vcredist_x86.exe.zip.exe");
}
}

public class GZipTest{
const int SIZE = 4096;
public static void Compress(String from, String to){

using (FileStream fs = new FileStream(from, FileMode.Open)) {
using (FileStream fsOutput = new FileStream(to, FileMode.Create, FileAccess.Write)) {
using (GZipStream zip = new GZipStream(fsOutput, CompressionMode.Compress)) {
byte[] input = new byte[SIZE];
int bytesRead;
while ((bytesRead = fs.Read(input, 0, SIZE)) > 0) {
zip.Write(input, 0, bytesRead);

}
}
}
}
}

public static void Decompress(String from, String to) {
using (FileStream fs = new FileStream(from, FileMode.Open)) {
using (FileStream fsOutput = new FileStream(to, FileMode.Create, FileAccess.Write)) {
using (GZipStream zip = new GZipStream(fs, CompressionMode.Decompress, true)) {
byte[] buffer = new byte[SIZE];
int bytesRead;
while ((bytesRead = zip.Read(buffer, 0, buffer.Length)) > 0) {
fsOutput.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
}


此類別適合單一 Stream 壓縮處理,如果要透過此類別來將多個檔案壓縮成 zip 檔比較不方便。也許可以可慮使用 j# 提供 java.util.zip 或使用
SharpZipLib

參考資料:
[1] .NET Tip: Compressing/Decompressing Your Files
[2] GZipStream 類別(System.IO.Compression)

2007年3月12日 星期一

[C++] 透過 STL Adapter 將函數和成員函數用於 for_each

MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.13 建立

本文主要示範 STL 中的 ptr_fun, mem_fun 和 mem_fun_ref 如何與 STL 演算法搭配使用。ptr_fun 能夠將一般函式當作仿函式使用,mem_fun 和 mem_fun_ref 用於成員函式指標。下面是針對這三個 Adapter 的範例程式:

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>

using namespace std;

class Shape{
public:
virtual void display()=0;
virtual ~Shape(){
cout << "Overn";
}
};

class Rect: public Shape{
public:
virtual void display(){
cout << "Rect" << endl;
}
};

class Circle: public Shape{
public:
virtual void display(){
cout << "Circle" << endl;
}
};

class Square: public Shape{
public:
virtual void display(){
cout << "Square" << endl;
}
};


typedef Shape* PShape;

void Delete(PShape ps){
delete ps;
}

int _tmain(int argc, _TCHAR* argv[])
{
vector<PShape> v;
v.push_back(new Rect());
v.push_back(new Circle());
v.push_back(new Square());

cout << "mem_fun" << endl;
for_each(v.begin(), v.end(), mem_fun(&Shape::display));

cout << "ptr_fun" << endl;
for_each(v.begin(), v.end(), ptr_fun(&Delete));

cout << "mem_func_ref" << endl;
vector<Rect> v2;
v2.push_back(Rect());
v2.push_back(Rect());
v2.push_back(Rect());
for_each(v2.begin(), v2.end(), mem_fun_ref(&Rect::display));

cin.get();
return 0;
}

透過這些 Adapter 我們可以很順利的將一般函式和成員函式用於 STL 演算法中。

2007年3月11日 星期日

透過 ADO.NET 查詢 Excel 內(*.xls)的資料

MSN SpaceGoogle DocGoogle Blog
Chui-Wen Chiu(Arick)
2007.03.12 建立

測試環境:
1. Windows XP Professional SP2
2. Visual Studio 2005
3. Microsoft Excel 2003

有時候我們可能需要從 Excel 萃取出我們所需要的資料,如果透過 Automation 還需要產生 Excel 實體有些麻煩,此時我們可以透過 ADO.NET 提供的 OleDbConnection 來連接 Excel 檔案,透過一致的存取方式來取得我們所需資料。

首先,我們先引入 System.Data 來取用 OleDbConnection, OleDbCommand 和 OleDbDataReader 等類別,下面就是一個簡單的查詢範例

using System;
using System.Data.OleDb;

namespace ImportExcelData {
class Program {
static void Main(string[] args) {
using (CExcel excel = new CExcel(@"c:student.xls")) {
OleDbDataReader reader = excel.DoQuery(@"SELECT [E-mail] FROM [student$] WHERE [E-mail] = 'a@hinet.net'");// Table 名稱對應格式為 [Sheet名稱$]
while (reader.Read()) {
Console.WriteLine(reader["E-mail"].ToString());
}
}
}
}

public class CExcel :IDisposable {
public CExcel(String excelFile) {
_excelConn = new OleDbConnection(String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;", excelFile) );
_excelConn.Open();
_command = new OleDbCommand();
_command.Connection = _excelConn;
}

public OleDbDataReader DoQuery(String sql) {
_command.CommandText = sql ;

return _command.ExecuteReader();
}

public void Close() {
if (_excelConn.State != System.Data.ConnectionState.Closed) {
_excelConn.Close();
}
}

public void Dispose() {
Close();
}

private OleDbConnection _excelConn;
private OleDbCommand _command;
}
}



參考資料:
http://www.c-sharpcorner.com/UploadFile/vandita/exceltoaccessinterop02242007093426AM/exceltoaccessinterop.aspx

搜尋此網誌