其中,資源是的范圍很廣,它可由多種元素組成,包括與用戶交互的界面元素(如位圖、圖標或光標)、應用程序所需數據的自定義文件以及安裝 API 使用的版本文件、菜單和對話框等都可以作為資源。為.Net程序集添加資源,就可實現資源重用等功能。使用Visual Studio.Net集成開發環境IDE很容易創建資源文件,把資源添加到工程中的方法和添加窗體、類庫一樣簡單,只是你需要設置資源的“BuildAction”屬性為“Embedded Resource”,這樣你就可以使用這些資源
創建資源
字符串表是極常見的一種資源。要創建這類資源文件,有以下兩種方式:
(1)使用.Net命令行工具ResGen創建。首先創建包含資源內容的文本文件,可使用(記事本、EditPlus等文本編輯器)。該文本文件由所需要的“鍵值對”組成,鍵的名稱可以在程序中引用,設置鍵名後把字符串值賦予該鍵即可完成文件的創建。作為示例,以下語句段產生這樣的資源,按下面的格式保存為userinfo.txt文件:
復制代碼 代碼如下:
Username="Songh";
Sex="Boy";
Birthday="1973-01-15";
Salary="5000RMB";
然後,把文本文件轉換為資源文件,這仍然通過ResGen工具來實現。執行以下語句:ResGen userinfo.txt,就將生成資源文件userinfo.resources。另外,ResGen還可以創建基於XML格式的.resX資源文件,執行以下命令ResGen userinfo.resources userinfo.resx 就將生成Xml格式的資源userinfo.resx。不過,ResGen工具不支持圖象資源的操作,下面的方法就不具有這樣的限制。
(2)使用ResourceWriter類。 為易於創建資源文件,.Net結構提供了ResourceWriter類以支持圖象等各種資源類型的創建。ResourceWriter類包含的方法能以系統默認的格式將資源寫入輸出文件或輸出流。與方法1)不同的是,這裡統一在一個過程中完成。
要創建一個資源文件,請調用ResourceWriter類的構造函數初始化類實例並至少提供流名或文件名。資源的實際內容通過調用AddResource方法來完成,AddResource方法將資源指定為名稱和值對。資源的實際寫入需要調用Generate方法來實現,不過,在調用Close方法關閉該ResourceWriter時將隱式調用Generate方法。
ResourceWriter.AddResource()方法向要寫入資源的列表中添加資源。在創建ResourceWriter類實例後,該方法可以添加至多2GB的資源,下面的重載方法之一用於向資源列表中添加string資源:
復制代碼 代碼如下:
public void AddResource(
string name,//鍵名
string value//值
);
在這裡,AddResource方法的第一個參數指定鍵名稱,第二個參數指定值。多次調用該方法就可以完成字符串表的創建。另外,添加圖象資源可以通過實例化類Image來實現(這時,請添加System.Drawing名稱空間)。
下面的代碼段生成包含字符串表和圖象的資源文件userinfo.resources。
復制代碼 代碼如下:
using System;
using System.Resources;
using System.Drawing;
public class RS
{
public static void Main()
{
ResourceWriter rw=new
ResourceWriter("userinfo.resources");//提供文件名以初始化ResourceWriter類實例。
Image image=Image.FromFile("photo.gif");//實例化Image類
rw.AddResource("Photo",image);//添加圖象
rw.AddResource("Username","songh");//添加字符串
rw.AddResource("Sex","boy");//添加字符串
rw.AddResource("Birthday","1973-01-15");//添加字符串
rw.AddResource("Salary","5000RMB");//添加字符串
rw.Close();//關閉ResourceWriter並隱式調用Generate()方法完成資源文件寫入磁盤文件。
}
}
上面的代碼首先打開圖形文件photo.gif,創建一個Image對象。這樣做時,這個圖形文件必須存在於工程可執行文件的目錄(通常是項目的\Bin\Debug目錄)下,或者在Image.FromFile()的方法參數中指定圖象的完整路徑。然後,通過幾次調用AddResouce()方法把字符串資源添加到ResourceWriter對象中。最後,調用Close()方法關閉ResourceWriter對象並隱式調用Generate()方法把資源寫入文件userinfo.resources。
編譯以上代碼並運行就將創建資源文件userinfo.resources。
以上兩種方式生成的資源文件均可以作為一個外部文件添加到程序集中,或者內嵌到Dll或exe中。下面繼續說明如何在Windows應用程序使用資源文件。
使用資源文件
使用Visual Studio.Net集成開發環境IDE,可以把很容易把資源文件添加到程序集中。只需要在創建的工程中添加已經存在的資源文件,簡單設置其屬性就可將資源文件嵌入該程序集。下面通過一個C# Windows控制台實例來說明任何使用上面創建的userinfo.resources資源文件。
首先,創建C# Windows Console項目ResourceUserinfo,打開"項目\添加現有項",找到前面創建的資源文件Userinfo.resources添加到這個工程中;
然後,選擇這個資源文件,將屬性BuildAction(生成操作)設置為Embedded Resource(嵌入的資源),這樣,資源文件就可以嵌入到輸出的程序集中。
現在,你可以使用這個資源文件了。System.Resources名稱空間中的ResourceManager類提供在運行時方便地訪問特定資源的途徑。具體地可以通過GetObject和GetString方法來實現,以鍵名為參數就將返回對應的值。
ResourceManager類的構造函數初始化ResourceManager類的新實例,其重載方法之一查找包含在一些文件中的資源,這些文件是使用給定的 Assembly 從指定根名稱導出的。
復制代碼 代碼如下:
public ResourceManager(
string baseName,
Assembly assembly
)
其中,參數baseName表示資源的根名稱。根名稱由應用程序名稱空間和資源文件名(不帶擴展名)組成。這樣,該例中資源的根名稱應該是:UserinfoResource.Userinfo,通過調用GetManifestResourceNames()方法也可編程獲取該名稱。
另一個參數assembly表示的是當前的主程序集,本例中的主程序集其實也是正在執行的程序集。獲取正在執行程序集的一個簡單方法是調用Assembly.GetExecutingAssembly()方法。
在獲取ResourceManager實例後,通過指定鍵名,就可以獲得對應的資源。
下表是程序中使用的部分控件:
類別 TextBox TextBox TextBox TextBox PictureBox
名稱 username sex birthday salary photo
這些控件均可直接從工具箱拖放到設計器中。
完整的源代碼為:
方法一:
復制代碼 代碼如下:
using System.reflection;
using System.Resources;
private System.Resources.ResourceManager rm;
public Form1()
{
InitializeComponent();
Assembly assembly=Assembly.GetExecutingAssembly();//獲取當前主程序集
Rm=new ResourceManager("ResourceUserinfo.Userinfo",assembly);//實例化資源管理類
photo.iamge=(Image)rm.GetObjetct("Photo");
username.Text=rm.GetString("Username");
sex.Text=rm.GetString("Sex");
birthday.Text=rm.GetString("Birthday");
salary.Text=rm.GetString("Salary");
}
方法二:
復制代碼 代碼如下:
Assembly assm = this.GetType().Assembly;//Assembly.LoadFrom(程序集路徑);
foreach (string resName in assm.GetManifestResourceNames())
{
Stream stream = assm.GetManifestResourceStream(resName);
ResourceReader rr = new ResourceReader(stream);
IDictionaryEnumerator enumerator = rr.GetEnumerator();
while (enumerator.MoveNext())
{
DictionaryEntry de = (DictionaryEntry)enumerator.Current;
//de.Key是資源名
//de.Value是資源內容
}
}
運行以上代碼,便可取出資源文件內容。
posted @ 2011-12-15 11:40 Tasting 閱讀(21) 評論(0) 編輯
DoDragDrop 方法的使用
DoDragDrop方法,用於開始對象的拖放操作。
在類庫中的定義為:
復制代碼 代碼如下:
[UIPermissionAttribute(SecurityAction.Demand, Clipboard = UIPermissionClipboard.OwnClipboard)]
public DragDropEffects DoDragDrop(
Object data,
DragDropEffects allowedEffects
)
其中data參數為要拖放的數據,如果拖動操作需要於另一個進程的應用程序相互操作,data代表的數據應該是基本托管類(String,BitMap,或MetaFile),或者是實現 ISerializable 或IDataObject的對象。 allowedEffects參數表示拖放的效果,為一個枚舉值(DragDropEffects).返回值也為DragDropEffects枚舉值。
當開始調用DoDragDrop方法拖動一個數據對象時,DoDragDrops在拖放過程中,檢測當前光標位置下的控件是不是有效的放置目標。如果當前光標下的控件是有效的放置目標,則GiveFeedBack事件以指定的拖放效果引發。在檢測當前位置光標是否為有效的拖放目標時,DoDragDrops方法同時跟蹤光標位置,鍵盤狀態和鼠標狀態的更改。
(1)如果用於移出了一個窗口,則引發DragLeave事件。
(2)如果移入了另外一個控件,則引發該控件的DragEnter事件。
(3)如果鼠標移動,但是停留在一個控件中,則引發DragOver事件。
如果檢測到更改了鍵盤或者鼠標狀態,則引發拖放源的QueryContinueDrag事件, 並根據事件的QueryContinueDragEventArgs的Action屬性值確定繼續拖動,放置數據或取消操作。
(1)如果Action屬性指定為Continue,則將引發DragOver事件。
(2)如果Action屬性指定為Drop,則將放置效果返回給源,以便應用程序對數據進行適當的操作;例如,如果是移動操作,則剪切數據。
(3)如果是DragAction的值為Cancel,則引發DragLeave事件
從csdn上摘抄一段示例代碼:
下面的代碼示例演示在兩個 ListBox 控件之間的拖放操作。當拖動動作啟動時,該示例調用 DoDragDrop 方法。在 MouseDown 事件期間,如果從鼠標位置起鼠標移動的距離大於 SystemInformation..::.DragSize,則啟動拖動動作。IndexFromPoint 方法用於確定在 MouseDown 事件期間要拖動的項的索引。
該示例還演示如何對拖放操作使用自定義光標。該示例要求應用程序目錄中存在兩個光標文件:3dwarro.cur 和 3dwno.cur,分別用於自定義拖動光標和禁止停放光標。如果選中 UseCustomCursorsCheckCheckBox,則使用自定義光標。自定義光標在 GiveFeedback 事件處理程序中設置。
鍵盤狀態在右 ListBox 的 DragOver 事件處理程序中計算,以確定基於 Shift、Ctrl、Alt 或 Ctrl+Alt 鍵的狀態將發生哪種拖動操作。放置動作在 ListBox 中發生的位置也在 DragOver 事件期間確定。如果要放置的數據不是 String,則 DragDropEffects 中將把 DragEventArgs.sEffect 設置為 None。最後,停放狀態在 DropLocationLabelLabel 中顯示。
要放置的用於右 ListBox 的數據在 DragDrop 事件處理程序中確定,並且在 ListBox 中的適當位置添加該 String 值。如果拖動操作移動到窗體邊框的外面,則 QueryContinueDrag 事件處理程序中將取消拖放操作
復制代碼 代碼如下:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Snip_DragNDrop
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox ListDragSource;
private System.Windows.Forms.ListBox ListDragTarget;
private System.Windows.Forms.CheckBox UseCustomCursorsCheck;
private System.Windows.Forms.Label DropLocationLabel;
private int indexOfItemUnderMouseToDrag;
private int indexOfItemUnderMouseToDrop;
private Rectangle dragBoxFromMouseDown;
private Point screenOffset;
private Cursor MyNoDropCursor;
private Cursor MyNormalCursor;
/// The main entry point for the application.
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
this.ListDragSource = new System.Windows.Forms.ListBox();
this.ListDragTarget = new System.Windows.Forms.ListBox();
this.UseCustomCursorsCheck = new System.Windows.Forms.CheckBox();
this.DropLocationLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
// ListDragSource
this.ListDragSource.Items.AddRange(new object[] {"one", "two", "three", "four",
"five", "six", "seven", "eight",
"nine", "ten"});
this.ListDragSource.Location = new System.Drawing.Point(10, 17);
this.ListDragSource.Size = new System.Drawing.Size(120, 225);
this.ListDragSource.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ListDragSource_MouseDown);
this.ListDragSource.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ListDragSource_QueryContinueDrag);
this.ListDragSource.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ListDragSource_MouseUp);
this.ListDragSource.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ListDragSource_MouseMove);
this.ListDragSource.GiveFeedback += new System.Windows.Forms.GiveFeedbackEventHandler(this.ListDragSource_GiveFeedback);
// ListDragTarget
this.ListDragTarget.AllowDrop = true;
this.ListDragTarget.Location = new System.Drawing.Point(154, 17);
this.ListDragTarget.Size = new System.Drawing.Size(120, 225);
this.ListDragTarget.DragOver += new System.Windows.Forms.DragEventHandler(this.ListDragTarget_DragOver);
this.ListDragTarget.DragDrop += new System.Windows.Forms.DragEventHandler(this.ListDragTarget_DragDrop);
this.ListDragTarget.DragEnter += new System.Windows.Forms.DragEventHandler(this.ListDragTarget_DragEnter);
this.ListDragTarget.DragLeave += new System.EventHandler(this.ListDragTarget_DragLeave);
// UseCustomCursorsCheck
this.UseCustomCursorsCheck.Location = new System.Drawing.Point(10, 243);
this.UseCustomCursorsCheck.Size = new System.Drawing.Size(137, 24);
this.UseCustomCursorsCheck.Text = "Use Custom Cursors";
// DropLocationLabel
this.DropLocationLabel.Location = new System.Drawing.Point(154, 245);
this.DropLocationLabel.Size = new System.Drawing.Size(137, 24);
this.DropLocationLabel.Text = "None";
// Form1
this.ClientSize = new System.Drawing.Size(292, 270);
this.Controls.AddRange(new System.Windows.Forms.Control[] {this.ListDragSource,
this.ListDragTarget, this.UseCustomCursorsCheck,
this.DropLocationLabel});
this.Text = "drag-and-drop Example";
this.ResumeLayout(false);
}
private void ListDragSource_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
// Get the index of the item the mouse is below.
indexOfItemUnderMouseToDrag = ListDragSource.IndexFromPoint(e.X, e.Y);
if (indexOfItemUnderMouseToDrag != ListBox.NoMatches) {
// Remember the point where the mouse down occurred. The DragSize indicates
// the size that the mouse can move before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width /2),
e.Y - (dragSize.Height /2)), dragSize);
} else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void ListDragSource_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) {
// Reset the drag rectangle when the mouse button is raised.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void ListDragSource_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty &&
!dragBoxFromMouseDown.Contains(e.X, e.Y)) {
// Create custom cursors for the drag-and-drop operation.
try {
MyNormalCursor = new Cursor("3dwarro.cur");
MyNoDropCursor = new Cursor("3dwno.cur");
} catch {
// An error occurred while attempting to load the cursors, so use
// standard cursors.
UseCustomCursorsCheck.Checked = false;
}finally {
// The screenOffset is used to account for any desktop bands
// that may be at the top or left side of the screen when
// determining when to cancel the drag drop operation.
screenOffset = SystemInformation.WorkingArea.Location;
// Proceed with the drag-and-drop, passing in the list item.
DragDropEffects dropEffect = ListDragSource.DoDragDrop(ListDragSource.Items[indexOfItemUnderMouseToDrag], DragDropEffects.All | DragDropEffects.Link);
// If the drag operation was a move then remove the item.
if (dropEffect == DragDropEffects.Move) {
ListDragSource.Items.RemoveAt(indexOfItemUnderMouseToDrag);
// Selects the previous item in the list as long as the list has an item.
if (indexOfItemUnderMouseToDrag > 0)
ListDragSource.SelectedIndex = indexOfItemUnderMouseToDrag -1;
else if (ListDragSource.Items.Count > 0)
// Selects the first item.
ListDragSource.SelectedIndex =0;
}
// Dispose of the cursors since they are no longer needed.
if (MyNormalCursor != null)
MyNormalCursor.Dispose();
if (MyNoDropCursor != null)
MyNoDropCursor.Dispose();
}
}
}
}
private void ListDragSource_GiveFeedback(object sender, System.Windows.Forms.GiveFeedbackEventArgs e)
{
// Use custom cursors if the check box is checked.
if (UseCustomCursorsCheck.Checked) {
// Sets the custom cursor based upon the effect.
e.UseDefaultCursors = false;
if ((e.Effect & DragDropEffects.Move) == DragDropEffects.Move)
Cursor.Current = MyNormalCursor;
else
Cursor.Current = MyNoDropCursor;
}
}
private void ListDragTarget_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
// Determine whether string data exists in the drop data. If not, then
// the drop effect reflects that the drop cannot occur.
if (!e.Data.GetDataPresent(typeof(System.String))) {
e.Effect = DragDropEffects.None;
DropLocationLabel.Text = "None - no string data.";
return;
}
// Set the effect based upon the KeyState.
if ((e.KeyState & (8+32)) == (8+32) &&
(e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) {
// KeyState 8 + 32 = CTL + ALT
// Link drag-and-drop effect.
e.Effect = DragDropEffects.Link;
} else if ((e.KeyState & 32) == 32 &&
(e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) {
// ALT KeyState for link.
e.Effect = DragDropEffects.Link;
} else if ((e.KeyState & 4) == 4 &&
(e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) {
// SHIFT KeyState for move.
e.Effect = DragDropEffects.Move;
} else if ((e.KeyState & 8) == 8 &&
(e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) {
// CTL KeyState for copy.
e.Effect = DragDropEffects.Copy;
} else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) {
// By default, the drop action should be move, if allowed.
e.Effect = DragDropEffects.Move;
} else
e.Effect = DragDropEffects.None;
// Get the index of the item the mouse is below.
// The mouse locations are relative to the screen, so they must be
// converted to client coordinates.
indexOfItemUnderMouseToDrop =
ListDragTarget.IndexFromPoint(ListDragTarget.PointToClient(new Point(e.X, e.Y)));
// Updates the label text.
if (indexOfItemUnderMouseToDrop != ListBox.NoMatches){
DropLocationLabel.Text = "Drops before item #" + (indexOfItemUnderMouseToDrop + 1);
} else
DropLocationLabel.Text = "Drops at the end.";
}
private void ListDragTarget_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
// Ensure that the list item index is contained in the data.
if (e.Data.GetDataPresent(typeof(System.String))) {
Object item = (object)e.Data.GetData(typeof(System.String));
// Perform drag-and-drop, depending upon the effect.
if (e.Effect == DragDropEffects.Copy ||
e.Effect == DragDropEffects.Move) {
// Insert the item.
if (indexOfItemUnderMouseToDrop != ListBox.NoMatches)
ListDragTarget.Items.Insert(indexOfItemUnderMouseToDrop, item);
else
ListDragTarget.Items.Add(item);
}
}
// Reset the label text.
DropLocationLabel.Text = "None";
}
private void ListDragSource_QueryContinueDrag(object sender, System.Windows.Forms.QueryContinueDragEventArgs e) {
// Cancel the drag if the mouse moves off the form.
ListBox lb = sender as ListBox;
if (lb != null) {
Form f = lb.FindForm();
// Cancel the drag if the mouse moves off the form. The screenOffset
// takes into account any desktop bands that may be at the top or left
// side of the screen.
if (((Control.MousePosition.X - screenOffset.X) < f.DesktopBounds.Left) ||
((Control.MousePosition.X - screenOffset.X) > f.DesktopBounds.Right) ||
((Control.MousePosition.Y - screenOffset.Y) < f.DesktopBounds.Top) ||
((Control.MousePosition.Y - screenOffset.Y) > f.DesktopBounds.Bottom)) {
e.Action = DragAction.Cancel;
}
}
}
private void ListDragTarget_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) {
// Reset the label text.
DropLocationLabel.Text = "None";
}
private void ListDragTarget_DragLeave(object sender, System.EventArgs e) {
// Reset the label text.
DropLocationLabel.Text = "None";
}
}
}
對用這種拖放操作和微軟的服務,容器模式的關系,留在以後再學習。
posted @ 2011-12-15 11:16 Tasting 閱讀(92) 評論(0) 編輯
關於接口的使用
概述: 接口的使用體現了一種泛化的思想。
應用場景之一是:
(1)多個類都要實現某些動作,而該動作具體實現的方式又不一樣。
如對於創建條件來的窗體來說,要實現添加整形參數,bool類型參數和字符串類型參數的條件添加的窗體。而在具體的實現整形和字符串的窗體,以及bool類型的添加的窗體過程中,實現細節又不一樣。
復制代碼 代碼如下:
public interface IExpressionForm
{
ConditionItemEntity CIEntity { get; set; }
ConditionBranchEntity CIEntity { get; set; }
event Handle OnExpressionHandled; }
而對於每個窗體來說,都需要包含CIEntity,CIEntity屬性和OnExpressionHandled添加條件後的事件,因此在IExpressionForm 接口中定義了CIEntity,CIEntity,和OnExpressionHandled。
接著實現整形參數的條件添加窗體
復制代碼 代碼如下:
public partial class frmNumericCondition : Form, IExpressionForm
{
public frmNumericCondition()
{
InitializeComponent();
}
public ConditionItemEntity CIEntity { get; set; }
public ConditionBranchEntity CBEntity { get; set; }
public event Handle OnExpressionHandled;
}
然後是字符型參數條件添加窗體
復制代碼 代碼如下:
public partial class frmVarcharCondition : Form, IExpressionForm
{
public frmVarcharCondition()
{
InitializeComponent();
}
public ConditionItemEntity CIEntity { get; set; }
public ConditionBranchEntity CBEntity { get; set; }
public event Handle OnExpressionHandled;
}
以此類推,實現其它參數類型條件添加的窗體。
那我這樣實現的目的的好處是什麼呢?接下來我們來看看,我定義的一個產生窗體的函數
復制代碼 代碼如下:
public static IExpressionForm CreateExpressionForm(ConditionType ct)
{
IExpressionForm frm = null;
if (ct == ConditionType.bit)
frm = new frmBitCondition();
else if (ct == ConditionType.datetime)
frm = new frmDateTimeCondition();
else if (ct == ConditionType.numeric)
frm = new frmNumericCondition();
else if (ct == ConditionType.varchar)
frm = new frmVarcharCondition();
return frm;
}
從定義中我們可以看出,返回值類型為IExpressionForm ,是我在上邊定義的接口。因此該函數可以返回一切實現了IExpressionForm 接口的類。如frmVarcharCondition 和frmNumericCondition.
這樣就簡單的實現了工廠模式,程序可以用很好的擴展性。
以上只是接口的應用場景之一,也是自己在寫代碼的時候發現的。寫的不好。但也要寫,一方面是要總結工作和學習,在總結的時候可以思考和發現,也希望能給閱讀文章的人一些幫助。