Thursday, August 12, 2004

Introducing the RoundedCorner Web Control

IntroductionMany professionally done sites group related options into aesthetically-pleasing "boxes". On Amazon.com, for example, the left-hand column contains a number of these boxes: Search, Browse, and so on. Each box has a bordered outline, with a title at the top. To gussy things up a bit, the title bar at the top of the box has rounded corners, as opposed to just square corners.
This is an example of text inside of a RoundedCorners control that has a width of 150 pixels. Neat, eh?
Creating a box with rounded corners isn't terribly difficult, and there's a myriad of ways for creating such design elements. Virtually all of the techniques, though, require using Photoshop or some other graphics editing program to create rounded corners of the appropriate color. For graphics designers, creating rounded corners must be extremely boring, and they likely hold as much interest in creating rounded corners as veteran ASP.NET developers do in creating a connection to a database. Been there, done that - thousands of times. But for non-graphics designers (like yours truly), creating these rounded corners can be frustratingly slow and annoying, especially if you're like me, and the only graphics editing program you have is Microsoft Paint.
To overcome this loathsome activity, I decided to create a custom ASP.NET server control that would utilize the dynamic image-creation capabilities of GDI+ to create the corner images for me. The result is an ASP.NET Web control, which I call RoundedCorners, that you can drop on an ASP.NET Web page, set a few properties, and be presented with a nifty box with rounded corners, as shown on the right. In this article we'll examine how to use the RoundedCorners Web control in a page, as well as take a peek under the covers at the control's source code.

Techniques for Creating Boxes with Rounded CornersBefore we delve into how to use the RoundedCorners control, let's first discuss some of the techniques that can be employed to create a box with rounded corners:
Create the box, rounded corners, and text, all as a single image.
Use a three-column, three-row HTML

. With this approach, the left-most and right-most columns in the top and bottom rows each contain one of the four corners. A variant of this approach is to create a one-column, three-row table, where the top and bottom rows are complete images themselves. (That is, rather than having to create just the corner, you create the entire bottom or top row as an image.)
Use CSS-related techniques. Typically a few nested tags are used with some relative positioning for the corners. For more information on using CSS simply Google CSS rounded corners, and you'll find a wealth of information.
With all of these approaches, however, one or more images are needed. (CSS3 offers the ability to create rounded corners and drop shadows without the use of images; unfortunately, CSS3 is still in the formation stages, and while some of its features are supported by some browsers, it's not anywhere close to being uniformly supported.)
The RoundedCorners Web control uses a 3x3 HTML
to create the rounded corners. For those CSS purists out there... well... sorry. The source code for this control is available at the end of this article, so you are more than welcome to modify the control to emit CSS syntax. (If you do enhance the control, though, please send me the updated version, as I can share it here with others.)
Using the RoundedCorners Web Control in an ASP.NET Web PageAt the end of this article you will find the complete source code as well as an assembly (a .dll file) compiled for the .NET Framework 1.1. If you are using Visual Studio .NET 2003, you can simply add the RoundedCorners control to your Toolbox by right-clicking on the VS.NET Toolbox, choosing Add/Remove Items, and browsing to the RoundedCorners assembly. (If you are using Visual Studio .NET 2002, you'll need to compile the provided source code and use that compiled assembly.) Once you have added the control to the Toolbox, adding it to an ASP.NET Web page is as simple as dragging the control from the Toolbox and dropping it onto the page's Designer.

Once you add the RoundedCorners control to an ASP.NET Web page, you'll be able to configure it's properties via the Properties pane. The germane properties for this control are:
BackColor - specifies the background color for the main area in the box.
BorderColor / BorderStyle / BorderWidth - specifies the border color, style, and width for the box.
CornerHeight / CornerWidth - specifies the height and width for the corner images. These default to 13 pixels, but you can tweak the size if needed. (If you have a large title row, you might need to make the corners higher than 13 pixels.)
Font - specifies the font style information for the box's text. (Font name, size, bold, italic, etc.)
ForeColor - specifies the foreground color of the box's text.
HorizontalAlign - indicates how the box is horizontally aligned.
ImageDirectory - the RoundedCorners control only creates the corner images on a per-demand basis. After a corner image is created, it is saved to the Web server's file system, so that the image need not be recreated for each page load from each visitor. The ImageDirectory property specifies the virtual directory where the images should go (i.e., /Images/).
Padding - the padding around the box's text.
RoundedBottom - determines whether or not rounded corners are also displayed at the bottom of the box. Defaults to True, meaning that rounded corners are placed on both the bottom and top.
TextHorizontalAlign - indicates how the text within the box is horizontally aligned.
Title - specifies the title for the box. If a title is specified, it is placed in the middle column of the

's top row.
TitleStyle - provides style information for the title row, such as background color, font information, and so on.
Width - indicates the width of the box. This is optional, but oftentimes you'll want to give an absolute width for the box, such as 150px.
You can configure all of the properties for RoundedCorners through the Visual Studio .NET Properties pane and Designer, or you can declaratively specify the property values. I have a series of live demos available where you can see the resulting rounded corners box and the declarative markup that goes with it.
Looking Under the Hood at the RoundedCorners Control's Source CodeThe code for the RoundedCorners server control is fairly straightforward. RoundedCorners is implemented as a composite control derived from the WebControl class. In the overridden CreateChildControls() method a Table is created with three TableRows, each with three TableCells. The upper-left, upper-right, bottom-left, and bottom-right cells display an appropriately rounded corner. The upper-middle cell displays the title, if specified.
The rounded corners are displayed by adding an Image Web control to the appropriate cells. This Image Web control is returned by a call to the method CreateCorner(). If one were to naively implement CreateCorner(), they'd have it use GDI+ to dynamically generate a rounded corner image each time is was called, but this is quite wasteful. Imagine a Web page has a box with rounded corners. When it is visited for the first time, these four corner images will be dynamically created. Now, if another user visits this same page, he'll need the same images; we could recreate them on the fly, but why not save the images from the first time they were created? The purpose of CreateCorner(), then, is to:
Check to see if an image file exists on the file system for the rounded corner.
If the file does not exist, dynamically create it and save it.
Return an Image Web control whose ImageUrl property equals the appropriate filename.
This is a pretty sensible approach, but there is one wrinkle. The rounded corner images are specific to a number of parameters, including:
Which of the four corners is being created,
The background color of the box,
The box's border color, style, and width, and
The specified height and width of the corner images.
For example, imagine that you have a box with a light blue background and a solid navy border with 1px width. When the page containing this rounded corner box is visited, the four corner images will be generated dynamically, and then saved to the file system. When subsequent visitors come, they'll be served the corner images that were saved to disk. Great. But now imagine that our page developer changes the background color to white. If he doesn't delete the associated corner images, visitors will now see a box with a white background, but whose corners have a light blue background!
To overcome this problem, we can give each corner a filename that spells out its defining characteristics. This is precisely what CreateCorner() does, as can be seen by the following code snippet. (Note that CreateCorner() takes in a parameter of type Corners - this is an enumeration with the four possible corner positions: UpperLeft, UpperRight, BottomLeft, and BottomRight.)
protected virtual System.Web.UI.WebControls.Image CreateCorner(Corners c)
{
// compute the file name
StringBuilder fileName = new StringBuilder(ImageDirectory, 75);
// start with the corner abbreviation
switch (c)
{
case Corners.UpperLeft:
fileName.Append("ul");
// now add the backcolor
if (TitleStyle.BackColor != Color.Empty)
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", TitleStyle.BackColor.R,
TitleStyle.BackColor.G, TitleStyle.BackColor.B);
else
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", BackColor.R,
BackColor.G, BackColor.B);
break;
case Corners.UpperRight:
fileName.Append("ur");
// now add the backcolor
if (TitleStyle.BackColor != Color.Empty)
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", TitleStyle.BackColor.R,
TitleStyle.BackColor.G, TitleStyle.BackColor.B);
else
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", BackColor.R,
BackColor.G, BackColor.B);
break;
case Corners.BottomLeft:
fileName.Append("bl");
// now add the backcolor
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", BackColor.R,
BackColor.G, BackColor.B);
break;
case Corners.BottomRight:
fileName.Append("br");
// now add the backcolor
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}", BackColor.R,
BackColor.G, BackColor.B);
break;
}
// now add in the borderColor
fileName.AppendFormat(".{0:x2}{1:x2}{2:x2}.", BorderColor.R,
BorderColor.G, BorderColor.B);
// add in the borderStyle
fileName.Append(BorderStyle.ToString());
// add in the corner width and height
fileName.AppendFormat(".{0}-{1}", CornerWidth, CornerHeight);
// finally add in the borderWidth
fileName.Append(".").Append(BorderWidth.ToString()).Append(".gif");
// if file doesn't exist, dynamically create the appropriate image
if (!File.Exists(HttpContext.Current.Server.MapPath(fileName.ToString())))
{
// file does not exist - create it
CreateRoundedCorner(c, fileName.ToString());
}
// Create an Image with the right filename and return it
System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image();
img.BorderWidth = Unit.Empty;
img.ImageUrl = fileName.ToString();
img.Height = CornerHeight;
img.Width = CornerWidth;
return img;
}
The filename is composed of two characters specifying what corner the image is for (upper-left, upper-right, ...), the HTML color value of its background color, the HTML color value of its border color, its border style, the height and width of the corner image, and the border width. For example, the image for a 13px by 13px upper-left corner with a blue background and a solid, black, 1px border would be: ul.0000ff.000000.Solid.13-13.1px.gif. A long filename, yes, but it uniquely identifies the corner image by utilizing its defining characteristics. This way, if the page developer changes the background color to white and the border width to 2px, the filename will change appropriately to: ul.000000.000000.Solid.13-13.2px.gif. (The filename is prepended with the value of the ImageDirectory property as well, as you can see in the initialization of the StringBuilder in the first line of the above method.)
After the filename has been determined, CreateCorner() checks to see if the file exists. If not, it calls CreateRoundedCorner(), which dynamically creates the image and saves it to the specified file path. Finally, a new Image Web control is instantiated and its ImageUrl property is set to the appropriate file path.
Dynamically Generating the Rounded Corner ImageCreating images of the fly in an ASP.NET Web page is not terribly difficult thanks to the GDI+ library. GDI+ is the term used to describe a set of classes in the .NET Framework for creating and manipulating images. Past articles on 4Guys - such as True Image Resizing, A Robust Image Gallery for ASP.NET, and Creating Snazzy Web Charts and Graphics On the Fly with ASP.NET - have shown how to utilize the GDI+ libraries to accomplish common image-related tasks.
The main challenge in creating or manipulating images with GDI+ is making those images look good. Since the corner images created for RoundedCorners are GIFs, I'll focus on the GDI+ issues with GIF files. When you create or open an image with the GDI+ classes, the classes use 32 bits per pixel, When you save a GIF file with GDI+, GDI+ dithers the image, reducing the palette to 256 Web-safe colors. The problem is that not all colors in the GIF will be accurately represented, which leads to a grainy looking image. The solution to overcoming grainy GIF images is to use quantization, which is the process of adjusting the GIF's palette so that it more closely matches the image's true colors, thereby resulting in a less grainy image.
Admittedly, I am no expert on image file formats and related algorithms, but fortunately there's a good article on MSDN by Morgan Skinner called Optimizing Color Quantization for ASP.NET Images, which looks at the problem in more details and provides a set of classes for performing quantization. The RoundedCorners Web control utilizes Morgan's Palette-based Quantization algorithm to "clean up" the graininess of the GIF image. Too, I modified the algorithm slightly so that the first palette color is the transparent color. This transparent color is used as the background of the corner images, so that if the rounded corner box is placed on a colored background, the background color shows through the area outside of the border of the rounded corner. (Specifically, in the GetPalette() method in PaletteQuantizer.cs I added palette.Entries[0] = Color.FromArgb(0, _colors[0]);, which sets the first palette item to transparent (that's what the 0 passed into FromArgb() indicates). In CreateRoundedCorner() I define the palette's entries, and make sure to cover the image with the first palette entry color initially, before adding the curve of the rounded corner.)
ConclusionIn this article we looked at RoundedCorners, a custom Web control I created to display a box with rounded corners without having to create any corner image files. RoundedCorners works by generating a 3x3 HTML
, with rounded corner images in each corner. These images are created on the fly, if necessary, and then saved to the Web server's file system so that they can be reused without having to be regenerated. To improve the quality of the image, I utilize Morgan Skinner's quantization routines, and tweaked them ever so slightly to make the first palette color the transparent one. The complete source code is downloadable at the end of this article.
Happy Programming!

Attachments:
Download the complete code (in ZIP format)
View a live demo



Using Resources for Localization with ASP.NET 2.0

Using Resources for Localization with ASP.NET 2.0

To localize a Web application we can use resource files. There a three way of using resources in ASP.Net 2.0 to localize a web application.

* Use ResourceManager to get a string programmatically
* Use Implicit Localization
* Use Explicit Localization

Many of you are probably already familiar with how to use the ResourceManager class to get a string from a resource file. So I will not spend some time writing about that. Instead I will focus on the two new localization features in Asp.Net 2.0, Implicit and explicit localization. If we should use the ResourceManager class, we have to programmatically get a string from a resource file with the GetString method and set the returned value to a control’s property or properties, such as the Text or ToolTip property of a TextBox control etc. But with the new implicit and explicit localization feature we don’t need to do it programmatically, the localization feature are doing this automatically for us.

Implicit Localization

To use implicit localization on a page, each page that should be localized must have its own resource file (.resx). The resource file contains each control on the page and the control’s properties and values that are marked with the “localizable” attribute:

[System.ComponentModel.Localizable(true)]
public string MyProperty
{
get { return this._value; }
set { this._value = value; }
}

Note: Most of the server control shipped with ASP.Net, such as TextBox, Label, Button etc has the LocalizableAttribute added to the properties that are text-based.”

There is a tool added to VS 2005 that will generate a resource for us. Before we generate a resource file, we need to add all the control’s that we are going to use on our page. To generate a file, choose Tools in the menu and select “Generate Resource file”.

Note: If you can’t find this option, you need to import the IDE settings for web application. You can do this by selecting the Tools menu, and Import/Export Settings, and choose Reset IDE settings and then select the “Web.vssettings” file located in the list box with installed settings files.

When we have generated a resource file, a LocalResource folder will be added to our web project root folder with will contain the resource file for our page. The resource file will contain each control added to the page and its properties with its values that are marked with the “Localizable” attribute:

Key Value
ButtonResource1.Text My Button’s Text
ButtonResource1.Tooltip My Button’s Tooltip

When the we have generated the resource file, it will also add a meta:resourcekey attribute to our control’s markup:



At runtime, ASP.Net will examine the controls one the page. If the control is marked with the meta:resourcekey attribute, ASP.Net will look in the resource file for the page, if it could find the property of the marked control, ASP.Net will substitute the values in the resource file for those in the control. To create a resource file for other languages, we have to make a copy of the generated resource file and add the ISO culture code to the file, for example if the page we generate a resource file has the name “default” the resource file will be “default.resx”. If we want to have a resource file for Swedish, we make a copy the default resource file “default.resx” and add the culture code for Swedish (sv-SE) before the .resx file extension “Default.sv-SV.resx”. As you may know the runtime will load the right resource file base on the current UI culture when we use the ResourceManager, It works the same way for both implicit and explicit localization.

The implicit localization must have a resource file for each page in our web application that should use localization. The disadvantage with implicit localization is that we could not reuse the strings in the resource file for other pages. If we want to reuse localized data located in a resource files and want more control over which properties we want to set, we can instead use explicit localization.

Explicit Localization

With explicit localization we will have more control over which properties that we want to set. To do this we are using an expression that will point to a resource file. The expression should be added to the control’s property that we want to set. For example:

">

This can be done either manually or through the property window of the control. In the property windows you select the dotted button right to the “Expressions” options, select the property you want to add an expression to and select Resources as the Expression type. In the “Expression Properties” window, you write the ClassName of the resource file as an value to the ClassName option, and in the ResourceKey option you write the name of the resource key you have added to you resource file.

The ClassName is the name of the resource file without any culture or .resx extension. It’s the base part of the resource file. For example if we have those files:

Strings.resx
Strings.sv-SE.resx

The LocalizedText should be ”Strings”.

We have to create our own resource file for each language and it would be placed into the Resources folder in our web project root folder. If the folder doesn’t exits, we create it. To create a resource file, we right click on our Resources folder, select “Add new Item” and select the “Assembly Resource file” template.

When a page runs the expression will be evaluated and the specified resource file will be loaded based on the current UI culture, and the resource key’s value specified in the expression will be set to the property of the control. The different between implicit and explicit localization is that explicit localization can have one or several resource files, but the implicit must have a resource file for each page.

Amazon Order

Order Placed: August 3, 2004
Order Total: $179.64
When will your items arrive?

Shipment #1:Shipment #2:Shipment #3:
3 items - delivery estimate: Aug 19, 2004 - Aug 27, 20044 items - delivery estimate: Aug 23, 2004 - Sept 2, 20041 item - delivery estimate: Aug 20, 2004 - Aug 30, 2004
Shipment #1: Shipped on August 4, 2004

Delivery estimate: Aug 19, 2004 - Aug 27, 2004 (More about estimates)1 package via International Shipping
Shipping Address: PIETREK LIN Taichung, TaiwanTaichung, 402Taiwan Shipping Speed: Standard International Shipping
Items Ordered
Price
1 of: Blackjack Attack: Playing the Pros' Way [Hardcover] By: Don Schlesinger
$39.99
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

1 of: Gregorian Strategy for Multiple Deck Blackjack [Paperback] By: Gregory Mannarino
$10.36
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

1 of: Blackjack Bluebook II: the simplest winning strategies ever published [Paperback] By: Fred Renzey
$16.00
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

Item(s) Subtotal:
$66.35
Shipping & Handling:
$17.59

-----
Total Before Tax:
$83.94

-----
Total for This Shipment:
$83.94
Shipment #2: Shipped on August 11, 2004

Delivery estimate: Aug 23, 2004 - Sept 2, 2004 (More about estimates)1 package via International Shipping
Shipping Address: PIETREK LIN Taichung, TaiwanTaichung, 402Taiwan Shipping Speed: Standard International Shipping
Items Ordered
Price
1 of: Professional Blackjack [Paperback] By: Stanford Wong
$13.97
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

1 of: Burning the Tables in Las Vegas: Keys to Success in Blackjack and in Life [Hardcover] By: Ian Andersen
$19.01
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

1 of: Knock-Out Blackjack: The Easiest Card-Counting System Ever Devised [Paperback] By: Olaf Vancura, Ken Fuchs
$12.57
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

1 of: Theory of Blackjack, 6th Edition [Paperback] By: Peter Griffin
$10.36
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

Item(s) Subtotal:
$55.91
Shipping & Handling:
$23.46

-----
Total Before Tax:
$79.37

-----
Total for This Shipment:
$79.37
Shipment #3: Shipped on August 6, 2004

Delivery estimate: Aug 20, 2004 - Aug 30, 2004 (More about estimates)1 package via International Shipping
Shipping Address: PIETREK LIN Taichung, TaiwanTaichung, 402Taiwan Shipping Speed: Standard International Shipping
Items Ordered
Price
1 of: Basic Blackjack [Paperback] By: Stanford Wong
$10.47
- 1 item(s) Gift options: - Gift-wrap: None - Gift note: Happy birthday!

Item(s) Subtotal:
$10.47
Shipping & Handling:
$5.86

-----
Total Before Tax:
$16.33

-----
Total for This Shipment:
$16.33
Payment Information

Item(s) Subtotal:
$132.73
Shipping & Handling:
$46.91

-----
Total Before Tax:
$179.64
Estimated Tax:
$0.00

-----
Grand Total:
$179.64Payment Method: MasterCard Last 5 digits: 12407Billing Address: PIETREK LIN Taichung, TaiwanTaichung, 402Taiwan

Monday, August 09, 2004

Page.Navigate(url)

I see this solution of redirecting a page very often, but in my framework
this method of the Page class doesn't exist, what is the correct sollution
of redirection a page in c# on a button click for example......?

I think what you want is the HttpResponse.Redirect method. You can use the
following code to redirect to an URL:

private void Button1_Click(object sender, System.EventArgs e)
{
Response.Redirect("http://www.microsoft.com";);
}

For more information about the HttpResponse.Redirect method please see:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfSystemWebHttpResponseClassRedirectTopic.asp

Friday, August 06, 2004

21點基本策略

H=要牌 ; S=不要牌 ; D=加注


SP= 分牌 ; Soft 13=A+2( 其他如此類推 )

























































































































閒家牌面

莊家牌面

2

3

4

5

6

7

8

9

10

A

5,6,7,8

H

H

H

H

H

H

H

H

H

H

9

H

D

D

D

D

H

H

H

H

H

10

D

D

D

D

D

D

D

D

H

H

11

D

D

D

D

D

D

D

D

D

H

12

H

H

S

S

S

H

H

H

H

H

13,14

S

S

S

S

S

H

H

H

H

H

15,16

S

S

S

S

S

H

H

H

H

H

17,18,19,20

S

S

S

S

S

S

S

S

S

S


url傳遞中文的解決方案

url傳遞中文的解決方案
1.設置web.config文件。(我不喜歡設置成這樣)

......

......

2.傳遞中文之前,將要傳遞的中文參數進行編碼,在接收時再進行解碼。
>> 進行傳遞
string Name = "中文參數";
Response.Redirect("B.aspx?Name="+Server.UrlEncode(Name));
>> 進行接收
string Name = Request.QueryString["Name"];
Response.Write(Server.UrlDecode(Name));

3.如果是從 .HTML 文件向 .Aspx 檔進行傳遞中文參數的話(即不從後臺用 Redirect()方法進行 Url 轉換)。一樣要將傳遞的中文參數進行編碼,在接收時再進行解碼。
>> 進行傳遞
,script language="JavaScript".
function GoUrl()
{
var Name = "中文參數";
location.href = "B.aspx?Name="+escape(Name);
}
,/script.

>> 進行接收
string Name = Request.QueryString["Name"];
Response.Write(Server.UrlDecode(Name));

一般來說。設置web.config檔就可以了。但是如果你用 JavaScript webservice 方法的話(往webservice裏面傳遞中文參數)。設置 web.config 檔好象無效。

Monday, July 12, 2004

Blog 已經建立

Blog 已經建立