通过图形和绘制事件自定义日历

问题描述

这是我自己的一个小项目,只是学习 WinForms 的图形等等。

目标是编写我自己的日历控件,以满足一些非常具体的要求。

以下是我处理 Paint 事件的方式(非常 hacky atm):

    private void XCalendar_Paint(object sender,PaintEventArgs e)
    {
        // Pen
        var pen_border = new Pen(BorderColorGrid);
        var pen_row_border = new Pen(BorderColorGridRow);
        var pen_column_border = new Pen(BorderColorGridColumn);

        //var grid_pen = new Pen(Color.Black);
        var bez_pen = new Pen(Color.FromArgb(192,241,231));

        var description_row_height = 30;
        var description_column_width = 65;

        // Calculate Full 
        int full_width = this.Width - 1 - description_column_width;
        int full_height = this.Height - 1 - description_row_height;

        if (this.Users.Count == 0)
        {
            var s = "Keine Benutzer gefunden.";
            var f = new Font(new FontFamily("Trebuchet MS"),12f);
            var s_size = e.Graphics.MeasureString(s,f);
            var p = new Point((int)(full_width / 2) - (int)(s_size.Width / 2) + 30,30);
            e.Graphics.DrawString(s,f,new SolidBrush(Color.FromArgb(180,180,180)),p);
            return;
        }

        // Calculate Rows
        int row_count = 0;
        switch (_calendarView)
        {
            case CalendarViews.Day:
                row_count = 1;
                break;
            case CalendarViews.Week:
                row_count = 7;
                break;
            case CalendarViews.Month:
                row_count = DateTime.DaysInMonth(DateTime.Now.Year,DateTime.Now.Month);
                break;
        }
        int row_height = full_height / row_count;

        // Calculate Columns
        int col_count = Users.Count;
        int col_width = full_width / col_count;

        // Draw Description Column BackColor
        var desc_col_rect = new Rectangle(new Point(1,description_row_height + 1),new Size(description_column_width - 1,full_height - 1));
        e.Graphics.FillRectangle(new SolidBrush(bez_pen.Color),desc_col_rect);

        // Draw Border
        var rect = new Rectangle(new Point(0,0),new Size(this.Width - 1,this.Height - 1));
        e.Graphics.DrawRectangle(pen_border,rect);

        var desc_font = new Font(new FontFamily("Trebuchet MS"),9f);
        var desc_brush = new SolidBrush(Color.Black);

        // Draw Columns
        var col_x = description_column_width;
        for (int x = 0; x < col_count; x++)
        {
            var rect_col = new Rectangle(new Point(col_x,1),new Size(col_width,description_row_height));
            var user = Users[x];
            var short_name = user.Shortname;
            var desc_size = e.Graphics.MeasureString(short_name,desc_font);
            e.Graphics.FillRectangle(new SolidBrush(user.Color),rect_col);
            e.Graphics.DrawLine(pen_column_border,new Point(col_x,full_height + description_row_height));
            e.Graphics.DrawString(short_name,desc_font,desc_brush,new Point(col_x + (int)(col_width / 2 - desc_size.Width / 2),(int)(description_row_height / 2 - desc_size.Height / 2)));

            col_x += col_width;
        }

        // Draw Rows
        var row_y = description_row_height;
        DateTime dt = this.StartDateTime == null ? DateTime.Now : StartDateTime;
        switch (this._calendarView)
        {
            case CalendarViews.Week:
                dt = DateTimeExtensions.StartOfWeek(dt,DayOfWeek.Monday);
                break;
            case CalendarViews.Month:
                dt = new DateTime(dt.Year,dt.Month,1);
                break;
        }

        for (int x = 0; x < row_count; x++)
        {
            var rect_row = new Rectangle(new Point(1,row_y),row_height));
            var s = new DateTimeFormatInfo().GetShortestDayName(dt.DayOfWeek) + "," + dt.ToString("dd.MM");
            var cur_row_fill_color = Color.Transparent;
            if (dt.Date == DateTime.Now.Date)
            {
                cur_row_fill_color = this.FillColorCurrentDateRow;
            }
            else if (dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday)
            {
                cur_row_fill_color = this.FillColorWeekendDays;
            }
            var s_size = e.Graphics.MeasureString(s,desc_font);
            e.Graphics.FillRectangle(new SolidBrush(cur_row_fill_color),rect_row);
            e.Graphics.DrawLine(pen_row_border,new Point(0,new Point(full_width + description_column_width,row_y));
            e.Graphics.DrawString(s,new Point((int)(description_column_width / 2 - s_size.Width / 2),row_y + 3));

            dt = dt.AddDays(1);
            row_y += row_height;
        }
    }

哪个工作得很好(设计方面):

enter image description here

日历将处理多个用户

enter image description here

当然,这只是一个简单的网格和一些矩形。不幸的是,我不能对矩形使用任何事件,因为它只是一个绘制的组件。

我希望能在这里得到一些关于如何处理可点击日历项目(如约会)的意见。将面板或用户控件随处放置对我来说听起来非常低效......?任何输入都将受到赞赏!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)