alarm.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,041 行 · 第 1/2 页

C
1,041
字号

    default:
        return( DefWindowProc( win_handle, msg, wparam, lparam ) );
    }
    return( 0L );

}



static seg_position  SegPosition[ NUMBER_OF_SEGMENTS ] =
/*******************************************************

    These are the positions of the start and end points
    of each digit segment segments based on the
    following co-ordinate system.


   (0,0) ---0--- (1,0)
        |       |
        1       2
        |       |
   (0,1) ---3--- (1,1)
        |       |
        4       5
        |       |
   (0,2) ---6--- (1,2)

*/
    /* start.x  start.y end.x   end.y */
{
    {  0,       0,      1,      0 },    /* 0 */
    {  0,       0,      0,      1 },    /* 1 */
    {  1,       0,      1,      1 },    /* 2 */
    {  0,       1,      1,      1 },    /* 3 */
    {  0,       1,      0,      2 },    /* 4 */
    {  1,       1,      1,      2 },    /* 5 */
    {  0,       2,      1,      2 },    /* 6 */
};

/*************************************************************************

    The following arrays define the polygon for each digit segment
    based on the two end points defined in SegPosition. Each entry
    is an (x,y) point based on the start or end point of the line
    segment plus some delta in the x and y direction. For example,
    START+UP_QUARTER+RITE_HALF means the starting point of the line
    segment, moved up 1/4 of a segment width, and rite 1/2 of a
    segment width
*/

typedef enum {
        START           = 0x0001,
        END             = 0x0002,
        DOWN_ONE        = 0x0004,
        UP_ONE          = 0x0008,
        DOWN_HALF       = 0x0010,
        UP_HALF         = 0x0020,
        DOWN_QUARTER    = 0x0040,
        UP_QUARTER      = 0x0080,
        LEFT_ONE        = 0x0100,
        RITE_ONE        = 0x0200,
        LEFT_HALF       = 0x0400,
        RITE_HALF       = 0x0800,
        LEFT_QUARTER    = 0x1000,
        RITE_QUARTER    = 0x2000
} point_delta;

static point_delta Poly0[] = {
        START+UP_QUARTER+RITE_QUARTER,
        END+UP_QUARTER+LEFT_QUARTER,
        END,
        END+DOWN_ONE+LEFT_ONE,
        START+DOWN_ONE+RITE_ONE,
        START,
        0
};

static point_delta Poly1[] = {
        START+DOWN_QUARTER+LEFT_QUARTER,
        END+UP_QUARTER+LEFT_QUARTER,
        END,
        END+UP_HALF+RITE_ONE,
        START+DOWN_ONE+RITE_ONE,
        START,
        0
};

static point_delta Poly2[] = {
        START+RITE_QUARTER+DOWN_QUARTER,
        END+UP_QUARTER+RITE_QUARTER,
        END,
        END+UP_HALF+LEFT_ONE,
        START+DOWN_ONE+LEFT_ONE,
        START,
        0
};

static point_delta Poly3[] = {
        START+UP_HALF+RITE_ONE,
        END+UP_HALF+LEFT_ONE,
        END,
        END+DOWN_HALF+LEFT_ONE,
        START+DOWN_HALF+RITE_ONE,
        START,
        0
};

static point_delta Poly4[] = {
        START+DOWN_QUARTER+LEFT_QUARTER,
        END+UP_QUARTER+LEFT_QUARTER,
        END,
        END+UP_ONE+RITE_ONE,
        START+DOWN_HALF+RITE_ONE,
        START,
        0
};

static point_delta Poly5[] = {
        START+RITE_QUARTER+DOWN_QUARTER,
        END+UP_QUARTER+RITE_QUARTER,
        END,
        END+UP_ONE+LEFT_ONE,
        START+DOWN_HALF+LEFT_ONE,
        START,
        0
};

static point_delta Poly6[] = {
        START+DOWN_QUARTER+RITE_QUARTER,
        END+DOWN_QUARTER+LEFT_QUARTER,
        END,
        END+UP_ONE+LEFT_ONE,
        START+UP_ONE+RITE_ONE,
        START,
        0
};

static point_delta *SegPoly[] =
{
    &Poly0,  &Poly1,  &Poly2,  &Poly3,  &Poly4,  &Poly5,  &Poly6
};


static void DrawSegment( HDC dc, pen_type pen,
                         seg_position *pos, point_delta *delta )
/***************************************************************

    Draw the polygon for a segment of a digit.
*/
{
    pixels      x,y;
    pixels      one_x,one_y;
    pixels      half_x,half_y;
    pixels      quarter_x,quarter_y;

    one_y = SegmentHeight;
    half_y = SegmentHeight / 2;
    quarter_y = SegmentHeight / 4;
    if( one_y <= 2 ) one_y = 1;
    one_x = SegmentWidth;
    half_x = SegmentWidth / 2;
    quarter_x = SegmentWidth / 4;
    if( one_x <= 2 ) one_x = 1;
    SelectObject( dc, Pens[pen] );
    MoveToEx( dc, pos->start.x, pos->start.y, NULL );
    while( *delta != 0 ) {
        if( *delta & START ) {
            x = pos->start.x;
            y = pos->start.y;
        } else if( *delta & END ) {
            x = pos->end.x;
            y = pos->end.y;
        }
        if( *delta & UP_QUARTER )       y -= quarter_y;
        if( *delta & UP_HALF )          y -= half_y;
        if( *delta & UP_ONE )           y -= one_y;
        if( *delta & DOWN_QUARTER )     y += quarter_y;
        if( *delta & DOWN_HALF )        y += half_y;
        if( *delta & DOWN_ONE )         y += one_y;
        if( *delta & LEFT_QUARTER )     x -= quarter_x;
        if( *delta & LEFT_HALF )        x -= half_x;
        if( *delta & LEFT_ONE )         x -= one_x;
        if( *delta & RITE_QUARTER )     x += quarter_x;
        if( *delta & RITE_HALF )        x += half_x;
        if( *delta & RITE_ONE )         x += one_x;
        LineTo( dc, x, y );
        ++delta;
    }
    LineTo( dc, pos->start.x, pos->start.y );
}


static BOOL SegmentOnInDigit[ 11 ][ NUMBER_OF_SEGMENTS ] =
/*********************************************************

    SegmentIsOn[ i ][ j ] indicates whether or not segment number i should
    be turned on in the digit j.
*/
{
/*    0      1      2      3      4      5      6        */
    {  TRUE,  TRUE,  TRUE, FALSE,  TRUE,  TRUE,  TRUE }, /* 0 */
    { FALSE, FALSE,  TRUE, FALSE, FALSE,  TRUE, FALSE }, /* 1 */
    {  TRUE, FALSE,  TRUE,  TRUE,  TRUE, FALSE,  TRUE }, /* 2 */
    {  TRUE, FALSE,  TRUE,  TRUE, FALSE,  TRUE,  TRUE }, /* 3 */
    { FALSE,  TRUE,  TRUE,  TRUE, FALSE,  TRUE, FALSE }, /* 4 */
    {  TRUE,  TRUE, FALSE,  TRUE, FALSE,  TRUE,  TRUE }, /* 5 */
    {  TRUE,  TRUE, FALSE,  TRUE,  TRUE,  TRUE,  TRUE }, /* 6 */
    {  TRUE,  TRUE,  TRUE, FALSE, FALSE,  TRUE, FALSE }, /* 7 */
    {  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE }, /* 8 */
    {  TRUE,  TRUE,  TRUE,  TRUE, FALSE,  TRUE,  TRUE }, /* 9 */
    { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, /* 10 */
};

static void DrawDigit( HDC dc, digit *p )
/****************************************

    Draw one digit of the the clock.
*/
{
    segment_index               i;

    for( i = 0; i < NUMBER_OF_SEGMENTS; ++i ) {
        if( SegmentOnInDigit[ p->value ][ i ] ) {
            if( !p->segment[i].on ) {
                DrawSegment( dc, FOREGROUND,
                             &p->segment[i].position, SegPoly[i] );
                p->segment[i].on = TRUE;
            }
        } else {
            if( p->segment[i].on ) {
                DrawSegment( dc, BACKGROUND,
                             &p->segment[i].position, SegPoly[i] );
                p->segment[i].on = FALSE;
            }
        }
    }
}


static void UpdateColon( HDC dc, colon_index i, pen_type *pen )
/**************************************************************

    Draw the colon separating the clock digits (and the AM/PM indicator)
*/
{
    dot_index           j;

    for( j = 0; j < NUMBER_OF_DOTS; ++j ) {
        if( Colons[i].dot[j].pen != pen[j] ) {
            SelectObject( dc, Pens[ pen[j] ] );
            Rectangle( dc, Colons[i].dot[j].top_left.x,
                           Colons[i].dot[j].top_left.y,
                           Colons[i].dot[j].bot_rite.x,
                           Colons[i].dot[j].bot_rite.y );
            Colons[i].dot[j].pen = pen[j];
        }
    }
}


static void DrawColon( HDC dc, colon_index i )
/*********************************************

    Draw the colon separating the digits. It flashes if seconds are supressed
*/
{
    pen_type    pen[NUMBER_OF_DOTS];

    pen[TOP_DOT] = FOREGROUND;
    if( !Setting && ( DigitsToDraw == DIGITS_WITHOUT_SECONDS ) &&
        ( ( Tick % 4 ) < 2 ) ) {
        pen[TOP_DOT] = BACKGROUND;
    }
    pen[BOT_DOT] = pen[TOP_DOT];
    UpdateColon( dc, i, pen );
}


static void DrawPM( HDC dc, BOOL pm )
/************************************

    Draw the AM/PM indicator (This is just a colon in front of the first digit
*/
{
    pen_type    pen[NUMBER_OF_DOTS];

    if( pm ) {
        pen[TOP_DOT] = BACKGROUND;
        pen[BOT_DOT] = FOREGROUND;
    } else {
        pen[BOT_DOT] = BACKGROUND;
        pen[TOP_DOT] = FOREGROUND;
    }
    UpdateColon( dc, 0, pen );
}


static void PaintClock( HDC dc )
/*******************************

    Paint the clock face on the screen
*/
{
    digit_index i;
    time_t      ltime;
    struct tm   *t;
    BOOL        pm;

    pm = FALSE;
    if( !Setting ) {
        time( &ltime );
        t = localtime( &ltime );
        if( TwelveHour ) {
            if( t->tm_hour > 12 ) {
                t->tm_hour -= 12;
                pm = TRUE;
            } else if( t->tm_hour == 0 ) {
                t->tm_hour = 12;
            }
        }
        ClockDigits[HOUR_TENS].value = t->tm_hour / 10;
        ClockDigits[HOUR_ONES].value = t->tm_hour % 10;
        ClockDigits[MIN_TENS].value = t->tm_min / 10;
        ClockDigits[MIN_ONES].value = t->tm_min % 10;
        ClockDigits[SEC_TENS].value = t->tm_sec / 10;
        ClockDigits[SEC_ONES].value = t->tm_sec % 10;
    } else {
        pm = AlarmPM;
    }
    if( ClockDigits[HOUR_TENS].value == 0 ) {
        ClockDigits[HOUR_TENS].value = BLANK_SPACE_VALUE;
    }
    for( i = 0; i < DigitsToDraw; ++i ) {
        DrawDigit( dc, &ClockDigits[i] );
    }
    DrawColon( dc, 1 );
    if( DigitsToDraw == DIGITS_WITH_SECONDS ) {
        DrawColon( dc, 2 );
    }
    if( TwelveHour ) {
        DrawPM( dc, pm );
    }
    if( ClockDigits[HOUR_TENS].value == BLANK_SPACE_VALUE ) {
        ClockDigits[HOUR_TENS].value = 0;
    }
}


static void SetColonPos( colon_index i )
/***************************************

    Set the screen positions for colon number "i".
*/
{
    pixels      dx,dy;
    pixels      add_x,add_y,sub_x,sub_y;
    pixels      x1,y1,x2,y2;

    y1 = ClockDigits[i].segment[SEGMENT_0].position.start.y;
    y2 = ClockDigits[i].segment[SEGMENT_6].position.start.y;
    switch( i ) {
    case 0:
        x1 = 0;
        x2 = ClockDigits[HOUR_TENS].segment[SEGMENT_0].position.start.x;
        break;
    case 1:
        x1 = ClockDigits[HOUR_ONES].segment[SEGMENT_0].position.end.x;
        x2 = ClockDigits[MIN_TENS].segment[SEGMENT_0].position.start.x;
        break;
    case 2:
        x1 = ClockDigits[MIN_ONES].segment[SEGMENT_0].position.end.x;
        x2 = ClockDigits[SEC_TENS].segment[SEGMENT_0].position.start.x;
        break;
    }
    dx = ( x2 - x1 ) / 2;
    dy = ( y2 - y1 ) / 3;
    add_x = dx / PORTION_FOR_COLON;
    sub_x = -add_x;
    if( add_x == 0 ) add_x = 1;
    add_y = dy / PORTION_FOR_COLON;
    sub_y = -add_y;
    if( add_y == 0 ) add_y = 1;
    x1 += dx;
    y1 += dy;
    Colons[i].dot[TOP_DOT].top_left.x = x1 + sub_x;
    Colons[i].dot[TOP_DOT].top_left.y = y1 + sub_y;
    Colons[i].dot[TOP_DOT].bot_rite.x = x1 + add_x;
    Colons[i].dot[TOP_DOT].bot_rite.y = y1 + add_y;
    Colons[i].dot[TOP_DOT].pen = BACKGROUND;
    y1 += dy;
    Colons[i].dot[BOT_DOT].top_left.x = x1 + sub_x;
    Colons[i].dot[BOT_DOT].top_left.y = y1 + sub_y;
    Colons[i].dot[BOT_DOT].bot_rite.x = x1 + add_x;
    Colons[i].dot[BOT_DOT].bot_rite.y = y1 + add_y;
    Colons[i].dot[BOT_DOT].pen = BACKGROUND;
}


static void InitializeTheClock( void )
/*************************************

    Initialize each digit of the clock. Calculate the screen position
    of each segment of each digit of the clock, as well as the
    screen positions of the colons.
*/
{
    pixels              win_left,win_rite;
    pixels              top_of_clock;
    pixels              top,bot;
    pixels              left,rite;
    pixels              width,height;
    pixels              space;
    pixels              colon_space;
    digit_index         i;
    segment_index       j;
    long                width_scale;
    long                height_scale;

    HeightOfClock = HeightOfWindow;
    if( HeightOfClock < MINIMUM_HEIGHT ) {
        HeightOfClock = MINIMUM_HEIGHT;
    }
    WidthOfClock = WidthOfWindow;
    height_scale = (long)ScreenHeightInMM * DIGIT_HEIGHT_SCALE;
    width_scale = (long)ScreenWidthInMM * DIGIT_WIDTH_SCALE / ( DigitsToDraw + 1 ); /* Allow for 2 colons */
    if( WidthOfClock * width_scale > HeightOfClock * height_scale ) {
        WidthOfClock = HeightOfClock * height_scale / width_scale;
    } else {
        HeightOfClock = WidthOfClock * width_scale / height_scale;
    }
    top_of_clock = ( HeightOfWindow - HeightOfClock ) / 2;

    top = HeightOfClock / UNUSED_PORTION_OF_SCREEN_HEIGHT;
    bot = HeightOfClock - top;
    height = bot - top;
    top += top_of_clock;

    win_left = WidthOfClock / UNUSED_PORTION_OF_SCREEN_WIDTH;
    win_rite = WidthOfClock - win_left;

    space = ( win_rite - win_left ) / ( DigitsToDraw + 1 );
    InterSegmentGap = space / PORTION_FOR_SEGMENT_GAP;
    SegmentWidth = space / PORTION_OF_SPACE_FOR_SEGMENT;
    SegmentHeight = (long)SegmentWidth * ScreenHeightInMM / ScreenWidthInMM;

    left = space / UNUSED_PORTION_OF_DIGIT_SPACE;
    rite = space - left;
    width = rite - left;

    for( i = 0; i < DigitsToDraw; ++i ) {
        for( j = 0; j < NUMBER_OF_SEGMENTS; ++j ) {
            ClockDigits[i].segment[j].on = FALSE;
            ClockDigits[i].segment[j].position = SegPosition[j];
            /* scale the co-ordinates */
            ClockDigits[i].segment[j].position.start.x *= width;
            ClockDigits[i].segment[j].position.end.x   *= width;
            ClockDigits[i].segment[j].position.start.y *= height / 2;
            ClockDigits[i].segment[j].position.end.y   *= height / 2;
            /* adjust for left edge of digit's bounding box and window */
            colon_space = i / 2 * ( width / 2 ); /* 0,1 -> 0, 2,3 -> 1/2 width, 4,5 -> width */
            ClockDigits[i].segment[j].position.start.x += colon_space + i * space + left + win_left;
            ClockDigits[i].segment[j].position.end.x   += colon_space + i * space + left + win_left;
            /* adjust for top edge of digit's bounding box */
            ClockDigits[i].segment[j].position.start.y += top;
            ClockDigits[i].segment[j].position.end.y   += top;
            /* adjust all edges for gap */
            if( SegPosition[j].start.x != SegPosition[j].end.x ) {
                ClockDigits[i].segment[j].position.start.x += InterSegmentGap;
                ClockDigits[i].segment[j].position.end.x -= InterSegmentGap;
            } else {
                ClockDigits[i].segment[j].position.start.y += InterSegmentGap;
                ClockDigits[i].segment[j].position.end.y -= InterSegmentGap;
            }
        }
    }
    for( i = 0; i < NUMBER_OF_COLONS; ++i ) {
        SetColonPos( i );
    }
}


static void ReSize( pixels width, pixels height, WORD type )
/***********************************************************

    Record the new size of the window and redraw the clock accordingly
*/
{
    WidthOfWindow = width;
    HeightOfWindow = height;
    DigitsToDraw = NumberOfDigits;
    if( type == SIZEICONIC ) {
        DigitsToDraw = DIGITS_WITHOUT_SECONDS;
    } else {
        DigitsToDraw = NumberOfDigits;
    }
    InitializeTheClock();
}

void CreateSupplies( void )
/**************************

    Create the art supplies we need
*/
{
    Pens[FOREGROUND] = CreatePen( 0, 1, GetSysColor( COLOR_WINDOWTEXT ) );
    Pens[BACKGROUND] = CreatePen( 0, 1, GetSysColor( COLOR_WINDOW ) );
}


void DeleteSupplies( void )
/**************************

    Delete our art supplies
*/
{
    DeleteObject( Pens[FOREGROUND] );
    DeleteObject( Pens[BACKGROUND] );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?