スポンサーサイト

  --, -- --:--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

精神レ○プ!IT土方と化した先輩

  03, 2016 16:54
たまにはラブライブ!以外のことも書いてみる

プログラミング単発ネタ
少し前まで仕事でC#をよく使っていて、カレンダーから一致した日付のデータを読み込むみたいな機能が必要になった
んで、Visual Studio2013に付属してるMonthCalendarというコントロールがあるから使ってみた結果、
・フォントサイズ変更不可(システムのフォントを使用しているため?)
・フォント太字不可(同上)
・日付ごとの背景色も変更不可(○とかの目印も付けれない)
・そもそもコントロール自体のサイズ変更ができない(月単位のサイズが変更できない)
monthcalendar01.png
こんな感じになる


うーんこの仕様
てかMonthCalendarってまんまWindowsタスクバー右下のやつなんだよなぁ・・・
time.png

これだとどう考えても使いにくいと思ったため、MonthCalendarを使う案は無しに
Web上で他の人が作ったよさそうなカレンダー探してみたが、案外見つからず...
というわけで必要最低限の機能を持った簡単なカレンダーを自作してみて、今回の記事に載せる前に少し改良と機能追加をしてみた

できたもの
calendar.png
(デザインセンスとかは)ないです
デザインセンスなんか必要ねぇんだよ!
< か > ボタンで次月か前月へ移動
コンボボックスで月選択可能
1年後 1年前 ボタンで年変更可能(1900~2099年まで対応)
DataGridViewを使用しているため、前述のMonthCalendarでできなかったことはできるようになってる
ちなみに3月15日は海未ちゃんの誕生日

動作(GIF画像上での表示がおかしかったため、画像差し替え)
preview02.gif
μ'sのキャラの誕生日がわかるというイミワカンナイ機能を追加してみた
やっぱりμ'sに関すること書いてるじゃないか(憤怒)
ラブライブ!以外のことを書く(大嘘)
祝日関連は色々面倒そうだからやってない


ついでで、ソースも公開してみるゾ
追記でソースと、VS上での使用方法など
ホラ、見ろよ見ろよ、ホラ
ソースの質が悪いのはゆるしてください!
なんでもしますから!



・Calendarクラスのソース

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
class Calendar
{
//μ'sメンバーの誕生日(サンプル用)
public string[] birth = new string[]{"01/17","03/15","04/19","06/09","07/22","08/03","09/12","10/21","11/01"};

///
/// DataGridViewカレンダー
///

/// データグリッドビュー
///
///
public void CalendarLoad(DataGridView dgv, int year, int month)
{
dgv.Rows.Clear();
//DGVのプロパティを設定
foreach (DataGridViewColumn c in dgv.Columns)
{
c.SortMode = DataGridViewColumnSortMode.NotSortable;
}
dgv.AllowUserToAddRows = false;
dgv.AllowUserToDeleteRows = false;
dgv.AllowUserToResizeColumns = false;
dgv.AllowUserToResizeRows = false;
dgv.MultiSelect = false;
dgv.ReadOnly = true;
dgv.RowHeadersVisible = false;
dgv.SelectionMode = DataGridViewSelectionMode.CellSelect;
dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dgv.DefaultCellStyle.Font = new Font("Meiryo UI", 18);
dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;

//年月の設定
DateTime ymd = new DateTime(year, month, 1);
DateTime preYmd = ymd.AddMonths(-1);

//月の最終日取得(28~31)
int mLength = DateTime.DaysInMonth(ymd.Year, ymd.Month);
int preLength = DateTime.DaysInMonth(preYmd.Year, preYmd.Month);

DayOfWeek week = ymd.DayOfWeek; //曜日取得
int start = (int)ymd.DayOfWeek; //曜日をint型にキャストする。土曜なら「6」、日曜なら「0」
int cellCount = start; //セル位置
int rowCount = 0; //行位置

//rowとcell作成
for (int i = 0; i < 6; i++)
{
DataGridViewRow newRow = new DataGridViewRow();
newRow.Height = 50;
newRow.CreateCells(dgv);
dgv.Rows.Add(newRow);
}

//前月31日~で埋める
for (int i = start - 1; i > -1; i--)
{
dgv.Rows[rowCount].Cells[i].Value = preLength;
dgv.Rows[rowCount].Cells[i].Style.Font = new Font("Meiryo UI", 11);
dgv.Rows[rowCount].Cells[i].Style.ForeColor = Color.LightGray;
preLength--;
}

//月初から月末まで
for (int i = 0; i < mLength; i++)
{
if (i + 1 != 1)
{
dgv.Rows[rowCount].Cells[cellCount].Value = i + 1;
}
//1日の位置
else
{
dgv.Rows[0].Cells[start].Value = i + 1;
}

//現在のセルの日付
DateTime tmp = new DateTime(year, month, i+1);

//背景色替えサンプル(μ's誕生日)
foreach (string s in birth)
{
if (tmp.ToString("MM/dd") == s)
{
dgv.Rows[rowCount].Cells[cellCount].Style.BackColor = Color.LimeGreen;
}
}

switch (cellCount)
{
//日曜
case 0:
dgv.Rows[rowCount].Cells[cellCount].Style.ForeColor = Color.Red;
//次のcellへ
cellCount++;
break;
//土曜
case 6:
dgv.Rows[rowCount].Cells[cellCount].Style.ForeColor = Color.Blue;
//土曜の場合、次のrowへ
cellCount = 0;
rowCount++;
break;
//上記以外
default:
//次のcellへ
cellCount++;
break;
}
}

//次月1日~で埋める
int day = 1;
for (int i = cellCount; i <7; i++)
{
dgv.Rows[rowCount].Cells[i].Value = day;
dgv.Rows[rowCount].Cells[i].Style.Font = new Font("Meiryo UI", 11);
dgv.Rows[rowCount].Cells[i].Style.ForeColor = Color.LightGray;
day++;
}
}
}
}


DGVで次のRowに移動するところのやり方はもっとスマートにやれなかったんですかね・・・

・Form1クラスのソース

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Calendar c = new Calendar();

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
YearTextBox.Text = DateTime.Now.Year.ToString();
MonthComboBox.Text = DateTime.Now.Month.ToString();
c.CalendarLoad(dataGridView1, DateTime.Now.Year, DateTime.Now.Month);
}

private void PrevMonthButton_Click(object sender, EventArgs e)
{
int month = int.Parse(MonthComboBox.Text);
int year = int.Parse(YearTextBox.Text);
switch (month)
{
case 1:
if (year > 1900)
{
MonthComboBox.Text = "12";
year--;
YearTextBox.Text = year.ToString();
}
break;
default:
month--;
MonthComboBox.Text = month.ToString();
break;
}
}

private void NextMonthButton_Click(object sender, EventArgs e)
{
int month = int.Parse(MonthComboBox.Text);
int year = int.Parse(YearTextBox.Text);
switch (month)
{
case 12:
if (year < 2099)
{
MonthComboBox.Text = "1";
year++;
YearTextBox.Text = year.ToString();
}
break;
default:
month++;
MonthComboBox.Text = month.ToString();
break;
}
}

private void NextYearButton_Click(object sender, EventArgs e)
{
YearLimit(2099, 1);
}

private void PrevYearButton_Click(object sender, EventArgs e)
{
YearLimit(1900, -1);
}

///
/// 年の制限
///

/// 限界値
/// 足し引きする値
private void YearLimit(int limit, int incdec)
{
int year = int.Parse(YearTextBox.Text);
//年が限界値に達したら何もしない
if (year == limit)
{
return;
}
else
{
year += incdec;
YearTextBox.Text = year.ToString();
}
}

private void YearMonth_Changed(object sender, EventArgs e)
{
if (MonthComboBox.Text != string.Empty && YearTextBox.Text != string.Empty)
{
int month = int.Parse(MonthComboBox.Text);
int year = int.Parse(YearTextBox.Text);
c.CalendarLoad(dataGridView1, year, month);
}
}

//DoubleClickイベントサンプル(μ's誕生日の通知)
private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
//ダブルクリックしたセルの日付取得
int year = int.Parse(YearTextBox.Text);
int day = (int)dataGridView1.CurrentCell.Value;
int month = int.Parse(MonthComboBox.Text);
DateTime date = new DateTime(year, month, day);

foreach (string s in c.birth)
{
if (date.ToString("MM/dd") == s && dataGridView1.CurrentCell.Style.ForeColor != Color.LightGray)
{
string member = "";
switch (s)
{
case "01/17":
member = "花陽ちゃん";
break;
case "03/15":
member = "海未ちゃん";
break;
case "04/19":
member = "真姫ちゃん";
break;
case "06/09":
member = "希ちゃん";
break;
case "07/22":
member = "にこちゃん";
break;
case "08/03":
member = "穂乃果ちゃん";
break;
case "09/12":
member = "ことりちゃん";
break;
case "10/21":
member = "絵里ちゃん";
break;
case "11/01":
member = "凛ちゃん";
break;
}
MessageBox.Show(date.ToString("MM月dd日") + "は、" + member + "の誕生日です!");
break;
}
}
}
}
}



・使用方法など
Visual Studioで下記のような感じでDataGridViewを作り、列の追加をして、曜日のヘッダーセルを作る
プロパティは特に変更しなくてOK(Calendarクラスで全て設定しているため)
フォームには、DGVとヘッダーセルを7個作成していることが必須条件
create01.png

ソース側で最低限必須なのは、上記のCalendarクラスと、FormのLoadイベントくらい
Formのロードイベントに以下を追加すれば動くと思う

private void Form1_Load(object sender, EventArgs e)
{
Calendar c = new Calendar();
c.CalendarLoad(dataGridView1, DateTime.Now.Year, DateTime.Now.Month);
}

CalendarLoadメソッドの引数はDGV、年、月


年月の各種boxとかはなくても動くが、あったほうがいいと思う
TextBoxのTextChangedイベントとComboBoxのSelectedIndexChangedイベントに以下のメソッドを参照させればOK

private void YearMonth_Changed(object sender, EventArgs e)
{
if (MonthComboBox.Text != string.Empty && YearTextBox.Text != string.Empty)
{
int month = int.Parse(MonthComboBox.Text);
int year = int.Parse(YearTextBox.Text);
c.CalendarLoad(dataGridView1, year, month);
}
}


ボタンもなくても動くが、必要であればForm1の各ボタンのClickイベントと、YearLimit()メソッドを参考にして、どうぞ
スポンサーサイト

- 1 Comments

Mon
2017.10.16
22:46

ニコ厨  

たまげたなぁ。これ便利すぎない?

2017/10/16 (Mon) 22:46 | REPLY |   

Post a comment

What's New

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。