(извиняюсь за назойливость)
Они ходят
Это вот иллюстрация к тому что я имел ввиду здесь:
http://rsdn.ru/Forum/Message.aspx?mid=1473872&only=1Автор: c-smile
Дата: 07.11.05
Этот самый behavior:clock в действии.
HTMLayout рисует элементы в три захода:
background, content и foreground
Данный конкретный behavior перекрывает только рисование content.
CSS задает две картинки
background:
и foreground:
(Последняя полупрозрачная — стекло — IE не умеет рисовать альфу).
Вот как выглядит CSS:
.clock {
behavior:clock; /* name defined in behavior_clock.cpp */
color:black; /* our behavior will use it for "hands" */
width:153px;
height:153px;
/* clock face */
background-image:url(clock-images/clock-back.png);
background-repeat:no-repeat;
background-position:50% 50%; /* middle center */
/* clock glass */
foreground-image:url(clock-images/clock-fore.png);
foreground-repeat:no-repeat;
foreground-position:50% 50%; /* middle center */
}
Т.е. в данном конкретном случае мы "реюзаем" все добавляя только
отрисовку контента.
Вот полный текст behavior_clock.cpp который оживляет картину:
(извиняюсь за полный текст, он не большой)
#include "stdafx.h"
#include "behavior_aux.h"
#include <math.h>
namespace htmlayout
{
/*
BEHAVIOR: clock
goal: Renders analog clock according to current tome.
TYPICAL USE CASE:
<img style="behavior:clock">
SAMPLE:
html_samples/behaviors/live-clock.htm
*/
struct clock: public behavior
{
// ctor
clock(): behavior(HANDLE_TIMER | HANDLE_DRAW, "clock") {} // здесь задается имя behavior для CSS
virtual void attached (HELEMENT he )
{
HTMLayoutSetTimer( he, 1000 ); // set one second timer
}
virtual void detached (HELEMENT he )
{
HTMLayoutSetTimer( he, 0 ); // remove timer
}
virtual BOOL on_timer (HELEMENT he )
{
dom::element el = he;
RECT rc = el.get_location(false);
HWND hw = el.get_element_hwnd(false);
::InvalidateRect(hw, &rc, FALSE);
return TRUE; /*keep going*/
}
virtual BOOL on_draw (HELEMENT he, UINT draw_type, HDC hdc, const RECT& rc )
{
if( draw_type != DRAW_CONTENT ) return FALSE; /* do default draw if not DRAW_CONTENT */
// we can get color settings from attributes but for simplicity lets use
// default values
SYSTEMTIME st;
GetLocalTime(&st);
//Use GetSystemTime(&st); - if you need clocks in UTC or other TZ
//you may use something like get_attribute("timezone")
draw_clock_hand(hdc,rc, (st.wHour * 360) / 12, 0);
draw_clock_hand(hdc,rc, (st.wMinute * 360) / 60, 1);
draw_clock_hand(hdc,rc, (st.wSecond * 360) / 60, 2);
return TRUE; /*skip default draw as we did it already*/
}
void draw_clock_hand( HDC hdc, const RECT& rc, int angle_degree, int hand )
{
double radians = (2 * 3.1415926 * (angle_degree - 90)) / 360.0 ;
int radius = min( rc.bottom - rc.top, rc.right - rc.left ) / 2 - 12;
HPEN hp = 0;
LOGBRUSH logbrush = { BS_SOLID, RGB(0,0,0), 0 };
logbrush.lbColor = ::GetTextColor(hdc);
switch(hand)
{
case 0: // hours
radius = (radius * 3) / 4;
hp = ::ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_ROUND, 5, &logbrush, 0,0);
break;
case 1: // minutes
hp = ::ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_ROUND, 3, &logbrush, 0,0);
break;
case 2: // seconds
logbrush.lbColor = RGB(0x7f,0,0);
hp = ::ExtCreatePen(PS_GEOMETRIC | PS_SOLID, 1, &logbrush, 0,0);
break;
default:
assert(false);
}
int y = (rc.bottom + rc.top) / 2;
int x = (rc.right + rc.left) / 2;
int xe = x + cos(radians) * radius;
int ye = y + sin(radians) * radius;
HGDIOBJ hpBefore = ::SelectObject(hdc,hp);
::MoveToEx(hdc,x,y,0);
::LineTo(hdc,xe,ye);
::SelectObject(hdc,hpBefore);
::DeleteObject(hp);
}
};
// instantiating and attaching it to the global list
clock clock_instance; // регистрация behavior для CSS
} // htmlayout namespace
--EOF
Это собственно демонстрация идеи: UI можно в принципе делать "малой кровью"
программируя только то что действительно надо прогаммировать.
Еще раз извиняюсь за настырность.