青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 67  文章 - 171  trackbacks - 0
<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

常用鏈接

留言簿(10)

隨筆分類

隨筆檔案

連接資料

最新隨筆

搜索

  •  

最新隨筆

最新評論

P1_DemoProgram.png

Introduction(http://www.codeproject.com/KB/GDI-plus/Style_Toolkit.aspx

If some of the styles above look familiar, they should. Many of them were derived from other articles on the CodeProject website. The Style Toolkit doesn’t use code from other articles, only definitions of things like colors, effects, border sizes, etc.

The Style Toolkit does not predefine styles, in the same sense that C++ does not predefine classes; therefore, the number of styles that it can create is infinite. Of course, once you have created a style, similar to creating a class, you can reuse it, modify it, and share it.

All the style components are created with layers, as if you were using a program like Photoshop; however, unlike Photoshop, all the layers are created programmatically. It doesn’t matter if it is a background, an indicator control, or an aqua button; they are all created by defining a sequence of graphics operations.

Background

The Style Toolkit uses GDI+; however, aside from the required initialization and the fact that it needs to compile and link correctly, it is transparent to the user. This article will not cover how to use and incorporate GDI+; if you are unfamiliar with it, read my GdipButton[^] article and other resources here on The Code Project.

Usage Preview

P2_TealPane.png

To demonstrate the power and simplicity of the Style Toolkit, let’s look at the Teal Pane of the demo program. I removed the controls, because they have their own style objects. The motivation for this style came from the Vista Info Bar[^] article.

The style above can be created with nine lines of code:

Collapse
void CStyleDemoDlg::CreateTealPane()
{
// create the stack
Stack TealPane(rect);
// set the OuterBorder params
TealPane.SetOuterBorder(2, Black);
// set the Inner Border params
TealPane.SetInnerBorder(2, RGB(135, 192, 185), RGB(109, 165, 168));
// 3 color gradient
TealPane.FillGrad3(HORIZ, RGB(9, 74, 116), RGB(32, 121, 140), RGB(5, 111, 90));
// add a top edge effect
TealPane.FillBar(rect, TOP_EDGE, 20, Clr(180,RGB(135, 192, 185)), Clr(0,White));
// add the shield image
TealPane.AddImage(CPoint(crnr.left, crnr.top),
IDR_SHIELD, _T("PNG"), 255);
// create a display string
CString str1(_T("Progress Styles\t\t\t    Indicator Styles"));
// add the string 
TealPane.AddString(str1, CPoint pt1(158, 35), RGB(148, 215, 255),
14, FONT_REG, L"Swiss")
// add to style
m_Style.AddStack(TealPane);
}

If you compare this to the Vista Info Bar source code, you can see how much more compact this is. Also, the Style Toolkit doesn’t use any external libraries, it only needs gdiplus.dll.

The code above doesn’t actually do any graphics operations, it only defines them. A subsequent call to PaintStyle() will paint the graphics objects.

Styles, Stacks, and Layers

Definitions for the terminology used by the Style Toolkit are as follows:

  • Layer – Conceptually, a layer in the Style Toolkit is similar to a layer in a program like Photoshop. Technically however, a layer is a structure that defines a graphics operation. A layer can define something like FillSolid, but it can also define things like AddImage or CreateRgn.
  • Stack – A stack is a collection of layers that has a sense of bottom and top. A stack also has a frame bounded by a rectangle that defines its clipping region. The stack has three borders with default widths of zero that will always be topmost. The Stack class is derived from the Layers class, and is really just a partition that contains all the user API functions.
  • Style – A style is a collection of stacks that also has a sense of bottom and top. The stacks may overlap or be disjoint. The Style class contains the primary user paint function, PaintStyle.

Using the Style Toolkit

Creating a style is just a matter of declaring a Stack with a bounding rectangle, adding some graphics operations, and then adding it to a Style object for painting. The simplest possible style is shown below.

BOOL CStyleDemoDlg::OnEraseBkgnd(CDC* pDC)
{
CDialog::OnEraseBkgnd(pDevC);
CRect rect;
GetClientRect(rect);
Stack stack(rect);
Style style;
style.AddStack(stack);
stack.FillSolid(Green);
style.PaintStyle(pDC, rect);
return TRUE;
}

In practice, you wouldn’t declare the stacks and styles in the erase function; you would just call the PaintStyle function there.

The Stack functions add graphics operations to an array that acts like a FIFO. The operations will be executed in the order that they are declared, so always start with the bottom layers and work towards the top.

Backgrounds and Borders

P3_BorderPane.png

Backgrounds

We have already seen how to create a background, let’s look at a few more. The background on the left is a JPEG image. You can use images in any format supported by GDI+, and they can also be partially transparent. The right hand side is a SolidFill, you can also use two or three color gradients that are horizontal, vertical, or diagonal.

Borders

A Stack has three borders that will always be on top regardless of where you declare them. They can have any width, but by default, they have zero width, so they aren’t used unless specified. The borders can be a RECTANGLE, ELLIPSE, ROUNDRECT, or TRANSITION.

The left side of the image above is an example of a transition border. The outer edge is rectangular and the inner edge is a round rect. The predefined borders are just for convenience, they are easy to declare because their relative positions are fixed, so you only have to declare the width.

You can also create borders without using the predefined ones, because a layer can also be any of the shapes above. The border on the right hand side in the above image was created with layers, by declaring a clipping region in the center and using gradient fills for the edges.

Style Controls

The initial version of the Style Toolkit supports button, edit and progress controls. More will be added as time permits.

StyleProgress

The StyleProgress control contains at least two stacks: a bottom stack that doesn’t change, and a top stack that changes when the control steps. The bottom stack can be just a clear layer, but it needs to exist for continuity reasons.

The StyleProgress can be a progress type, or an indicator type. The difference is that an indicator type represents how much of something (like a thermometer), it is not expected to step to the end like a progress control. The control doesn’t actually know which type it is, it all depends on how the stacks are defined.

P4_Progress.png

The default style is the Vista looking one in the upper left. If you don’t add any stacks to the control, it will create that style. The definitions for the default style came from Xasthom’s VistaProgressBar[^] article. You can change the colors of the default control by calling SetBackColor and SetForeColor.

The second progress bar just uses a gradient layer for the bottom and an elliptical gradient layer for the top. The motivation for this style came from Kochise’s CSkinProgress[^] article. His control actually uses a PNG image and has a few hundred more features than mine.

The top indicator bar doesn’t step the colored layer. It can’t because it would always be green to red, regardless of the position. It actually steps a clear layer on top of the colored layer which defines the clipping region.

The bottom indicator was motivated by Hans Dietrich’s XGradientZoneBar[^] article, but I added an additional wrapping gradient to give it the hump effect.

The arrows are StyleButtons that can be used to step the bars.

StyleButton

The StyleButton is an extended version of my GdipButton[^]. It has all the features of the GdipButton (like pressed state, hot state etc.), but it also has the ability to use Style objects instead of images. The StyleButton can use different styles for each of its states. They are loaded with functions like LoadStdStyle(style1) and LoadHotStyle(style2). Typically, you only need a single stack to create one of the states, but the functions take style arguments so they can call the paint function.

At a minimum, you must call LoadStdStyle() or LoadStdImage(). States that are not set by a load function will be automatically derived from the standard state.

P5_VistaStyle1.png

The VistaStyle1 Pane shows most of the different states the button can have. The definitions for this button were roughly derived from Jose Manuel Menéndez Poó’s article WindowsVistaRenderer[^]. Only the top two buttons (a normal button and a check type button) are fully implemented, the other four are forced to an alternate state for illustration purposes.

Implementing Styles for a Button

I chose this button style for the demo program because of its complexity. The way to create these buttons is to separate them into their unique components, or stacks in the toolkit terminology. For example, most of the states share the same base, or share the same glow, etc. When creating the style states, we just assemble the correct pieces together. The Stack class overloads the operators “=”, “+”, and “+=”, these will be described in more detail in the API section.

After defining the different operations needed to create each stack (not shown here), we just assemble the different pieces needed for each of the button states.

// create standard group
VBStd = VB1Base;
// create the hot group
VBHot = VB1Base2 + VB1Hover + VB1Glow;
// create the pressed group
VBPress = VB1Base2 + VB1Pressed + VB1Glow;
// create the alt group
VBAlt = VB1Base2 + VB1Checked + VB1Hover + VB1CheckedGlow;

VB1Base and VB1Base2 are different because the borders are different. Also note that in this implementation, the glow does not bleed over the borders. It makes more sense to me that if something is glowing behind a piece of glass, it can’t also be in front of it. The bleed over style could be implemented by just defining it differently.

After creating the different stacks, we just add them to a style and then load them into the StyleButton.

More Button Styles

P6_MoreButtons.png

Buttons can be rectangular, elliptical, or rounded as shown here.

The definitions for the aqua style buttons were derived from the The Aqualizer Strikes Back[^] article.

The definitions for the Vista Style 2 buttons were derived from Xasthom’s Vista Style Button in C#[^] article.

The arrow buttons don’t use styles; they use a PNG file for the standard image and allow the StyleButton class to generate the other states.

StyleEdit

The StyleEdit class is derived from CEdit, and has the capability of adding a style to it. It also centers the text vertically, in addition to whatever horizontal centering may already be set. The demo program shows a few gradients with borders, I kept it simple so the text is readable. This class needs a few more tweaks and features, but I ran out of time, and it is good enough for the initial release.

Style Toolkit API

The Style Toolkit API is defined in the Style.h file.

All the API functions will take GDI or GDI+ type arguments. For example, you could pass COLORREF, CRect, and CPoint to a particular function, but you could also pass Color, Rect, and Point to the same function. The reason is because the actual API arguments are Clr, SRect, and SPoint, which are conversion classes. Internally, everything is stored in GDI+ format.

Overloaded Operators

The Stack class overloads operators “=”, “+”, and “+=”.

stack1 = stack2;

The = operator is the copy constructor, and behaves as you would expect. The layers in a stack are STL vectors, and the copy constructor will copy all the vectors in addition to doing a few housekeeping tasks. Images, strings, and regions are separate vectors, which are also copied.

stack1 += stack2;

The += operator in this example adds everything from stack2 to stack1, except the frame. Since the frame contains the borders and clipping region, stack2’s borders will be ignored and all its layers will be clipped by stack1’s bounding rectangle and shape.

stack1 = stack2 + stack3;

In this example, stack1 will contain the frame from stack2 and the layers from both stacks. The stack2 object will not be modified.

Templates

Templates are technically not part of the Style Toolkit, since you don’t need them to create styles. A template is just a mechanism that may be used to define, maintain, and share a style.

A template in the Style Toolkit is not the same as a C++ template. A C++ template is used to apply a set of behaviors to many different things; a Style Toolkit template is more analogous to a wood working template, which is used to make many copies of the same thing. For example, if a program has ten buttons, a mechanism is needed to make multiple copies of the same style, without having to define it ten times.

Since a style is just a data set, there are multiple ways you could go about creating a template. A style could be stored to an ASCII file or an XML file; however, I chose to use classes since it is a fairly simple method.

In the class method, you just define a class, add some stacks or styles as member variables, and define all the layers in the constructor. See the Templates.h and Templates.cpp files for examples.

Scope

You may notice when looking though the code that stacks are never declared with the new operator. The reason is because stacks are intended to be temporary construction objects. What makes a stack’s data permanent is when it is added to a style. The AddStack function will copy all the data to the style object, and the construction stack will be destroyed when it goes out of scope. Style objects are usually declared as member functions of a class, which gives them their permanence.

Even when a stack is declared as a member variable of a template class, the template classes themselves are temporary construction objects that are destroyed when they go out of scope.

Transparency

The bottom pane of the demo program demonstrates the use of transparency. All the components of a style can be anything from fully opaque to fully transparent. You can define the transparency of a color by using the Color class or the Clr class. If you do not declare the transparency, it will be fully opaque. For example, to define a semi-transparent blue, you would use Clr semiblue(128,RGB(0,0,255)).

Graphics Efficiency

Stacks are actually only “painted” once — the first time that they are used. Once a stack has painted all of its layers, it creates a bitmap bounded by its frame. Any subsequent paint call to the stack just copies the bitmap to the device context. The exception to this is when the stack’s Regenerate function is used. The Regenerate function marks the stack as “dirty”, and it will be repainted the next time it is needed.

When the PaintStyle function is called, it copies all the “clean” stack bitmaps to the device context. The reason it copies them individually is because the style doesn’t know if any of the stacks are “dirty” until it iterates through them.

There is no practical limit to the number of layers and stacks you can have. Also, using the Style Toolkit is not slower than using GDI+ directly. The reason for this is because stacks and layers are really just nested loop counters of the Style object that define a sequence of graphics operations. Defining the operations in an array versus calling them with subsequent lines of code doesn’t change the number of graphics operations needed. The Style Toolkit does all its painting in memory, then copies the end result to the screen.

How to Efficiently Use the Style Toolkit

In order to minimize paint operations, create different stacks for things that are dynamic versus static. For example, the progress control’s background never changes, so it has its own stack that only gets painted once. The foreground needs to be regenerated every time a step occurs, so it is in a separate stack.

Any stack on top of a stack that has been marked for regeneration also needs to be marked for regeneration by the user. Even though an upper stack itself may not have changed, its background did, and therefore its bitmap is incorrect. The toolkit doesn’t do this automatically since it doesn’t keep track of, or care about, the relative positions of stacks.

Needless to say, if a layer is completely covered by another layer or stack which is not at least partially transparent, then it should be removed. The stack code does not attempt to identify and/or remove any redundant paint operations.

Issues and Workarounds

GDI+ has a few issues that will create unexpected results.

  • Asymmetry – GDI+ has symmetry problems when it comes to creating rounded rectangles. See my RoundRect[^] for details. I have implemented workarounds for some if not all of these issues in the Border class. The Border class is an extended version of the RoundRect class.
  • Artifacts – GDI+ will sometimes create artifacts (extra lines that shouldn’t be there) when using a GradientBrush. If this occurs, try one of the following:
    • Change the size of the object with the artifact. This is the easiest method and it usually works, but it may not be an acceptable solution.
    • Try different Smoothing and Interpolation modes. This sometimes works, but it also has a tendency to move the problem around.
    • If the artifact occurs when using the AddEdgeEffect function, try using the profile version, and adjust the profile parameters until the artifact disappears.
  • Delayed Painting – The controls won’t be painted until they get the Windows message telling them to do so, which introduces some delay. If there are many controls like in the demo program, they will tend to pop in, after the background has been painted. This is a rather undesirable effect, and can be circumvented by pre-painting the control onto the background. The control still paints itself later, but you can’t tell because it is painting the same thing. See the Vista Style 2 or Aqua Style buttons for examples on how to do this.

Final Comments

The demo programs were compiled with VC6 and VS2005, and tested on Windows XP. However, the Style Toolkit should work with any compiler and platform that supports GDI+.

More controls and features will be added as time permits. If you would like a specific control added, request it in the message section.

posted on 2008-08-15 21:40 cpsprogramer 閱讀(1706) 評論(1)  編輯 收藏 引用 所屬分類: VC++

FeedBack:
# re: Style Toolkit - Use advanced graphics techniques to create a custom user interface 2012-06-20 11:03 4kzeng
哥以為你會用這個LIB,原來你也沒有使用經(jīng)驗.  回復(fù)  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              久久久久久日产精品| 亚洲精品久久久久久久久| 亚洲午夜小视频| 亚洲乱码久久| 国产精品久久一级| 久久成人人人人精品欧| 久久久xxx| 亚洲久久成人| 亚洲一区二区三区国产| 国产日韩一区| 亚洲成人在线网站| 亚洲女性裸体视频| 在线综合欧美| 极品av少妇一区二区| 欧美~级网站不卡| 欧美日本免费| 欧美激情一区| 国产精品一二三四区| 久久国产精品99国产| 久久久免费观看视频| 正在播放亚洲一区| 久久成人免费网| 一区二区三区免费网站| 性做久久久久久久久| 亚洲日本中文字幕免费在线不卡| 夜夜爽99久久国产综合精品女不卡| 国产精品丝袜白浆摸在线| 欧美jizzhd精品欧美喷水 | 久久福利精品| 欧美高清视频免费观看| 欧美一区二粉嫩精品国产一线天| 美日韩免费视频| 欧美一区网站| 欧美视频免费在线| 欧美国产日韩一区二区| 国产三级欧美三级| 亚洲图片在线| 一本一本大道香蕉久在线精品| 久久精品最新地址| 午夜久久一区| 一区二区三区国产在线| 伊人久久久大香线蕉综合直播| 艳女tv在线观看国产一区| 亚洲日本视频| 蜜臀av一级做a爰片久久| 欧美在线播放视频| 国产精品久久国产三级国电话系列 | 欧美绝品在线观看成人午夜影视| 久久久99免费视频| 国产精品色网| 亚洲香蕉成视频在线观看| 一级日韩一区在线观看| 免费不卡视频| 欧美国产一区二区三区激情无套| 国产亚洲精品自拍| 亚洲尤物视频网| 亚洲制服丝袜在线| 欧美三级午夜理伦三级中视频| 亚洲欧洲在线一区| 91久久精品www人人做人人爽| 久久精品夜色噜噜亚洲aⅴ| 久久不射网站| 国产在线视频不卡二| 欧美一区成人| 狂野欧美一区| 亚洲黄色成人久久久| 嫩草国产精品入口| 亚洲国产日韩欧美在线动漫| 亚洲黄色片网站| 欧美精品v日韩精品v韩国精品v | 欧美在线视频全部完| 国产精品美女在线观看| 亚洲一区二区三区在线看| 欧美一区二区在线免费观看 | 国产精品久久久久国产精品日日| 日韩一级黄色av| 午夜精品久久久久久久99水蜜桃 | 一区二区三区视频在线观看| 亚洲专区在线视频| 国产久一道中文一区| 欧美一区亚洲二区| 欧美sm视频| 一区二区欧美国产| 国产精品伊人日日| 久久夜色精品| 99国产精品视频免费观看一公开| 亚洲在线日韩| 狠狠综合久久av一区二区小说 | 久久精品成人欧美大片古装| 欧美成人午夜免费视在线看片 | 亚洲精品精选| 国产欧美日本在线| 免费欧美日韩国产三级电影| 亚洲精品美女在线| 久久精品国产69国产精品亚洲 | 一区二区亚洲精品| 欧美日韩伊人| 久久琪琪电影院| 亚洲视频axxx| 亚洲国产小视频| 欧美综合77777色婷婷| 亚洲人精品午夜| 国产亚洲观看| 欧美色综合天天久久综合精品| 欧美一区二区三区四区在线观看| 亚洲福利小视频| 欧美一区二区性| 亚洲视频成人| 亚洲精品国偷自产在线99热| 国产日产亚洲精品系列| 欧美激情第10页| 久久久国产午夜精品| 亚洲一区二区精品| 亚洲第一网站免费视频| 久久久国产91| 午夜精品99久久免费| 99re8这里有精品热视频免费 | 亚洲欧美另类综合偷拍| 91久久一区二区| 在线播放中文字幕一区| 国产精品毛片一区二区三区| 欧美国产综合视频| 久久青青草原一区二区| 欧美一级理论性理论a| 一区二区三区福利| 亚洲茄子视频| 欧美激情免费在线| 欧美1区3d| 久久亚洲国产精品日日av夜夜| 亚洲女同同性videoxma| 亚洲一区二区免费在线| 亚洲精品中文字| 亚洲三级网站| 亚洲日本aⅴ片在线观看香蕉| 激情久久久久| 国产综合激情| 影视先锋久久| 激情综合久久| 亚洲成色www8888| 久久激情婷婷| 影院欧美亚洲| 好吊妞**欧美| 在线播放中文一区| 亚洲国产婷婷香蕉久久久久久99| 国产在线视频欧美| 在线观看欧美视频| 91久久精品国产91性色tv| 亚洲欧洲精品一区二区三区不卡 | 欧美日韩国产天堂| 欧美日韩综合视频网址| 国产精品国产三级国产普通话99 | 久久精品首页| 另类亚洲自拍| 欧美成人有码| 欧美日韩一区综合| 国产美女精品在线| 激情亚洲一区二区三区四区| 亚洲第一色在线| 亚洲免费久久| 午夜精品久久久久久久男人的天堂| 亚洲欧美日韩精品久久久| 小黄鸭精品aⅴ导航网站入口| 香蕉久久a毛片| 老妇喷水一区二区三区| 欧美激情第10页| 在线亚洲欧美| 久久久久久久久久久久久久一区 | 亚洲一区二区视频在线| 久久久精品欧美丰满| 欧美成在线观看| 国产精品你懂的| 在线观看亚洲视频啊啊啊啊| 日韩视频在线播放| 香蕉成人伊视频在线观看| 免费观看久久久4p| 999亚洲国产精| 久久国产加勒比精品无码| 欧美不卡高清| 国产精品一区二区久久久| 又紧又大又爽精品一区二区| 一区二区91| 免费高清在线一区| 亚洲午夜电影| 欧美高清视频www夜色资源网| 国产精品v欧美精品∨日韩| 激情六月综合| 香蕉久久精品日日躁夜夜躁| 美国十次了思思久久精品导航| 亚洲精品欧美日韩| 久久久综合视频| 国产精品免费看| 亚洲美女在线视频| 久久久夜夜夜| 亚洲一区二区三区四区五区午夜| 久久视频在线免费观看| 国产精品一区二区三区四区五区| 亚洲精品久久久久久久久| 免费观看欧美在线视频的网站| 午夜精品久久| 国产精品亚洲综合色区韩国|