乗りログ > たまにはプログラミングネタ その2 マルチモニタの状態を描画してみる

 何かちょうど一週間ぶりでした。
新バージョンのMultiWallpaperで一番変化が大きい、SQLite関連を色々やっていましたが疲れたので後回し。
今日はMultiWallpaperのメイン部分であるマルチモニタの状態を描画するところを書き直してみました。
2006年1月に作ってから手を加えていなく、自分でも何が何だか分からなくなったので…
以下にC#のソースを示します(pbxPreviewという名前のPictureBoxに描画します)

#region マルチモニタ状態での合計幅・合計高さを求める
int[] screen_location_X = new int[screen_length], screen_location_Y = new int[screen_length], screen_end_X = new int[screen_length], screen_end_Y = new int[screen_length];

//変数に入れておく
for (int screen_number = 0; screen_number < screen_length; screen_number++) { screen_location_X[screen_number] = Screen.AllScreens[screen_number].Bounds.Location.X; screen_location_Y[screen_number] = Screen.AllScreens[screen_number].Bounds.Location.Y; screen_end_X[screen_number] = screen_location_X[screen_number] + Screen.AllScreens[screen_number].Bounds.Width; screen_end_Y[screen_number] = screen_location_Y[screen_number] + Screen.AllScreens[screen_number].Bounds.Height; } //プライマリモニタの左上を基準として一番小さい値をscreen_min_Xとscreen_min_Yに入れる int screen_min_X = screen_location_X[0], screen_min_Y = screen_location_Y[0]; for (int screen_number = 0; screen_number < screen_length; screen_number++) { screen_min_X = Math.Min(screen_min_X, screen_location_X[screen_number]); screen_min_Y = Math.Min(screen_min_Y, screen_location_Y[screen_number]); } //プライマリモニタの左上を基準として一番大きい値をscreen_max_Xとscreen_max_Yに入れる int screen_max_X = screen_end_X[0], screen_max_Y = screen_end_Y[0]; for (int screen_number = 0; screen_number < screen_length; screen_number++) { screen_max_X = Math.Max(screen_max_X, screen_end_X[screen_number]); screen_max_Y = Math.Max(screen_max_Y, screen_end_Y[screen_number]); } //マルチモニタ状態での左上(=プライマリモニタの左上を基準として一番小さい値)を基準とした一番大きい値(合計幅・合計高さ)に変換する screen_max_X = screen_max_X - screen_min_X; screen_max_Y = screen_max_Y - screen_min_Y; #endregion #region PictureBoxに表示 Graphics g = pbxPreview.CreateGraphics(); //上の合計幅・合計高さを何倍すればPictureBoxに収まるか計算 double multiple = Math.Min(((double)pbxPreview.Width / (double)screen_max_X), ((double)pbxPreview.Height / (double)screen_max_Y)); //モニタごとに線を引いていく for (int screen_number = 0; screen_number < screen_length; screen_number++) { g.DrawRectangle(new Pen(Color.Red), (int)((screen_location_X[screen_number] + System.Math.Abs(screen_min_X)) * multiple), (int)((screen_location_Y[screen_number] + System.Math.Abs(screen_min_Y)) * multiple), (int)(Screen.AllScreens[screen_number].Bounds.Width * multiple), (int)(Screen.AllScreens[screen_number].Bounds.Height * multiple)); } g.Dispose(); #endregion

一応これでモニタの位置がどうなっていてもきちんと描画出来るはず…ギリギリすぎるのかたまにはみ出ますけど…
MultiWallpaperではこれを真ん中に描画するようにしたものを使っています。

 とりあえずこれで動いていますが、思いついたままに書いているのでもっと良いやり方や修正するべきところがあると思います。
そのあたりに気がつかれた方、是非コメントをお願いします。

コメントを残す

メールアドレスが公開されることはありません。