/// <summary> /// Check to see if the planetary hour (or lunar phase, if applicable) has changed. If so, notify the user /// </summary> private void phTick(object sender, System.EventArgs e) { if (pHours.CurrentHour() == (PlanetaryHours.Planet)(-1)) // Planetary day changed; recalculate hours { pHours = new PlanetaryHours(conf); // Just in case new hour is same as last recorded hour, but the computer had been suspended currentHour = (PlanetaryHours.Planet)(-2); // -2 because pHours.CurrentHour() could be -1 upon error. } if (currentHour != pHours.CurrentHour()) { currentHour = pHours.CurrentHour(); NotifyUser(); updateTray(); if (currentHour == (PlanetaryHours.Planet)(-1)) { ErrorMessage("An internal error has occured", new Exception("pHours.CurrentHour returns -1 twice - unable to calculate planetary hours"), conf); } } if (conf.Caption == Config.CaptionType.LunarPhase && currentPhase != localPhases.CurrentPhase(DateTime.UtcNow)) { localPhases = new LunarPhase(DateTime.UtcNow); currentPhase = localPhases.CurrentPhase(DateTime.UtcNow); updateTray(); } }
/// <summary> /// This is called after the user clicks "Apply" or "OK" in the Properties form, in case the locality has changed. /// </summary> public void RefreshHours() { pHours = new PlanetaryHours(conf); if (pHours.CurrentHour() == (PlanetaryHours.Planet)(-1)) { ErrorMessage("Unable to determine the current planetary hour.", new Exception("pHours.GetHour returns null at UTC" + DateTime.UtcNow.ToString()), conf); } initContextMenu(); if (conf.Caption == Config.CaptionType.LunarPhase) { localPhases = new LunarPhase(DateTime.UtcNow); currentPhase = localPhases.CurrentPhase(DateTime.UtcNow); } updateTray(); if (currentHour != pHours.CurrentHour()) { currentHour = pHours.CurrentHour(); NotifyUser(); } phClock.Interval = conf.Interval(); }
public NotifyWindow(PlanetaryHours pHours, Config conf) : this(pHours.DayString(), pHours.CurrentHourString(), conf, pHours.CurrentEnglishHour(), conf.PlanetColor(pHours.CurrentHour()), conf.NotifyFont, pHours.CurrentHourNum() == 0 ? true : false, conf.Sticky) { }
public ErrorReport(string msg, Exception ex, Config conf, PlanetaryHours pHours) { InitializeComponent(); if (msg == null) { labelError.Text = "An unknown error has occurred. ChronosXP cannot continue."; } else { labelError.Text = msg; } textBox.Text = ex.Message + "\r\n"; string st; if (ex.StackTrace == null) { st = new StackTrace(true).ToString(); } else { st = ex.StackTrace; } if (ex.Source != null) { st += "\r\nSource=" + ex.Source; } if (ex.TargetSite != null) { st += "\r\nTargetSite=" + ex.TargetSite; } textBox.Text += st + "\r\n"; try { textBox.Text += Config.FormatVersion() + " (Build " + Application.ProductVersion + ")\r\n"; } catch { textBox.Text += "Unknown ChronosXP version??? ProductVersion=" + Application.ProductVersion.ToString() + "\r\n"; } try { textBox.Text += Config.OSVersion() + " (" + Environment.OSVersion.ToString() + ")\r\n"; } catch { textBox.Text += "Unknown OS version??? OSVersion=" + Environment.OSVersion.ToString() + "\r\n"; } textBox.Text += ".NET Framework " + Environment.Version.ToString() #if MONO + " (Mono-compiled)" + #endif +"\r\n"; textBox.Text += "Thread.CurrentThread.CurrentCulture=" + System.Threading.Thread.CurrentThread.CurrentCulture.ToString() + "\r\n"; textBox.Text += "Thread.CurrentThread.CurrentUICulture=" + System.Threading.Thread.CurrentThread.CurrentUICulture.ToString() + "\r\n"; try { if (!conf.LoadOK) { textBox.Text += "Configuration: LoadOK=false\r\n"; } } catch { } try { textBox.Text += String.Format("Architecture={0}, Platform={1}\r\n", Config.Architecture, Config.Platform); } catch { } try { textBox.Text += String.Format("ZoneSysApplyDST={0}, RunFromTray={1}, RunFromTrayNow={2}, CurrentZone={3}\r\n", conf.ZoneSysApplyDST.ToString(), conf.RunFromTray.ToString(), conf.RunFromTrayNow.ToString(), conf.CurrentZone); } catch { } try { textBox.Text += String.Format("CurrentCulture={0}, ZenithDistance={1}, Language={2}, Place={3}, LPlace={4}\r\n", conf.CurrentCulture, conf.ZenithDistance, conf.Language, conf.DPlace, conf.LPlace); } catch {} try { textBox.Text += String.Format("SoundName={0}, SoundFile={1}, Sound={2}\r\n", conf.SoundName, conf.SoundFile, conf.Sound.ToString()); } catch {} try { textBox.Text += String.Format("Startup={0}, CheckUpgrade={1}, UseGradient={2}, ShowSeconds={3}\r\n", conf.Startup.ToString(), conf.CheckUpgrade.ToString(), conf.UseGradient.ToString(), conf.ShowSeconds.ToString()); } catch {} try { textBox.Text += String.Format("ShortInterval={0}, Notify={1}, Sticky={2}\r\n", conf.UseShortInterval.ToString(), conf.NotifyHour.ToString(), conf.Sticky.ToString()); } catch {} try { textBox.Text += "DefaultPlace=" + conf.DefaultPlace.ToString() + "\r\n"; } catch {} try { textBox.Text += "DefaultLocality=" + conf.DefaultLocality.ToString() + "\r\n"; } catch {} try { textBox.Text += "User Error=" + labelError.Text + "\r\n"; } catch {} try { textBox.Text += "Run=" + conf.Run.ToString() + "\r\n"; } catch {} if (pHours == null) { textBox.Text += "pHours=null\r\n"; } else { textBox.Text += "pHours=" + pHours.ToString() + "\r\n"; } textBox.Text += "DateTime.Now=" + DateTime.Now.ToString() + "\r\n" + "DateTime.UtcNow=" + DateTime.UtcNow.ToString() + "\r\n"; }
public ChronosXPCore(System.Windows.Application entry) { Entry = entry; Application.ApplicationExit += new System.EventHandler(appExit); Application.Idle += new System.EventHandler(appIdle); conf = new Config(this); if (!conf.LoadOK) { Shutdown(); return; } string[] args = Environment.GetCommandLineArgs(); bool showproperties = false; // The command-line arguments should only be used for testing, or internally foreach (string arg in args) { switch (arg.ToLower()) { case "/english": conf.Language = Config.CultureEN; break; case "/nederlands": case "/dutch": conf.Language = Config.CultureNL; break; case "/español": case "/espanol": case "/spanish": conf.Language = Config.CultureES; break; case "/italiano": case "/italian": conf.Language = Config.CultureIT; break; case "/français": case "/francais": case "/french": conf.Language = Config.CultureFR; break; case "/português": case "/portugues": case "/portuguese": conf.Language = Config.CulturePT; break; case "/hungarian": case "/magyar": conf.Language = Config.CultureHU; break; case "/greek": conf.Language = Config.CultureGR; break; case "/hebrew": conf.Language = Config.CultureHE; break; case "/standalone": conf.RunFromTrayNow = false; break; case "/tray": conf.RunFromTrayNow = true; break; case "/properties": showproperties = true; break; case "/nogradient": conf.UseGradient = false; break; case "/gradient": conf.UseGradient = true; break; case "/nocheckupdate": checkUpdate = false; break; case "/fastcheckupdate": fastCheckUpdate = true; break; #if BETA case "/debugnotify": debugnotify = true; break; // This is to create screen-shots (for the web page) of a BETA, but make it look like a release. Use with // /currentculture=(culture), to set Thread.CurrentCulture (which prints the VisualMonthCalendar in that language) // /photogenic implies /debugnotify case "/photogenic": Photogenic = true; debugnotify = true; break; #endif default: if (arg.ToLower().StartsWith("/zenith=")) { string[] zz = arg.Split(new char[] { '=' }, 2); try { conf.ZenithDistance = double.Parse(zz[1]); } catch { MessageBox.Show(conf.GetString("Core.InvalidArgument") + ": " + arg, "ChronosXP", MessageBoxButtons.OK, MessageBoxIcon.Error); Shutdown(); return; } } else if (arg.ToLower().StartsWith("/iconset=")) { string[] zz = arg.Split(new char[] { '=' }, 2); if (zz[1].ToLower().Equals("silver") || zz[1].ToLower().Equals("black") || zz[1].ToLower().Equals("multi")) { conf.Fx.IconSet = zz[1]; } else { MessageBox.Show(conf.GetString("Core.InvalidArgument") + ": " + arg, "ChronosXP", MessageBoxButtons.OK, MessageBoxIcon.Error); Shutdown(); return; } } else if (arg.ToLower().StartsWith("/currentculture=")) { string[] zz = arg.Split(new char[] { '=' }, 2); try { conf.CurrentCulture = new CultureInfo(zz[1]); Application.CurrentCulture = conf.CurrentCulture; Thread.CurrentThread.CurrentUICulture = conf.CurrentCulture; } catch { MessageBox.Show("Unsupported culture: " + zz[1], "ChronosXP", MessageBoxButtons.OK, MessageBoxIcon.Error); Shutdown(); return; } } else { continue; //MessageBox.Show (conf.GetString ("Core.InvalidArgument") + ": " + arg, "ChronosXP", // MessageBoxButtons.OK, MessageBoxIcon.Error); //Application.Exit(); //return; } break; } } // tray mode? initialize the NotifyIcon, ContextMenu and Timer, and calculate planetary hours. if (conf.RunFromTrayNow) { initTray(); pHours = new PlanetaryHours(conf); currentHour = pHours.CurrentHour(); updateTray(); if (conf.Caption == Config.CaptionType.LunarPhase) { localPhases = new LunarPhase(DateTime.UtcNow); currentPhase = localPhases.CurrentPhase(DateTime.UtcNow); } // This timer checks to see if the planetary hour has changed; if so, notify the user (if applicable) and change the NotifyIcon // and it's ToolTip text. phClock = new System.Windows.Forms.Timer(); phClock.Interval = conf.Interval(); phClock.Tick += new System.EventHandler(phTick); phClock.Start(); // This timer periodically updates the system tray icon; this is to ensure that the ChronosXP is not hidden with the // inactive icons, and also because of a bug that makes the icon distorted after doing a <Windows key>+L trayClock = new System.Windows.Forms.Timer(); trayClock.Interval = 55555; trayClock.Tick += new System.EventHandler(trayTick); trayClock.Start(); // When in tray mode, bind Alt+F11 to open the Planetary Hours Calendar (see this.WndProc) PInvoke.RegisterHotKey(Handle, 101, PInvoke.MOD_ALT, PInvoke.VK_F11); } #if WINDOWS if (conf.Run == 1) // First time ChronosXP is run? Prompt user to configure locality { DialogResult res = MessageBox.Show(conf.GetString("Core.WelcomeText"), conf.GetString("Core.WelcomeTitle"), MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { ShowProperties(); } else { MessageBox.Show(conf.GetString("Core.NoConfigText"), conf.GetString("Core.NoConfigTitle"), MessageBoxButtons.OK, MessageBoxIcon.Information); } } #endif #if BETA if (conf.BetaExpiry.CompareTo(DateTime.Now) <= 0) // Beta expired? Prompt user to upgrade { auxThread = new Thread(new ThreadStart(threadBetaExpired)); auxThread.Start(); if (conf.RunFromTrayNow) { betaClock = new System.Windows.Forms.Timer(); betaClock.Interval = 2255555; betaClock.Tick += new System.EventHandler(betaWarnTick); betaClock.Start(); } } else #endif // BETA #if WINDOWS // First, second or third time ChronosXP is run? Notify user that its running in the background with a balloon window if (conf.Run < 3 && conf.RunFromTrayNow) { auxThread = new Thread(new ThreadStart(threadBgRunning)); auxThread.Start(); } #endif // WINDOWS //if !DEBUG CheckUpdates(); //endif / DEBUG // standalone mode? display the Planetary Hours Calendar if (!conf.RunFromTrayNow) { ShowCalendar(); } // run with /properties argument? Show the Properties form. if (showproperties) { ShowProperties(); } }
/// <summary> /// Update the tray icon /// </summary> private void updateTray() { if (conf.Caption == Config.CaptionType.LunarPhase && localPhases == null) { localPhases = new LunarPhase(DateTime.UtcNow); currentPhase = localPhases.CurrentPhase(DateTime.UtcNow); } if (currentHour == (PlanetaryHours.Planet)(-1)) { pHours = new PlanetaryHours(conf); currentHour = pHours.CurrentHour(); } if (currentHour == (PlanetaryHours.Planet)(-1)) { trayIcon.Icon = new Icon(conf.Fx.ResourceStream("Exclamation.ico")); ErrorMessage("A serious internal error has occured; please report this error to the author of ChronosXP at " + Config.Email, new Exception("ChronosXP.PlanetaryHours failed twice at " + DateTime.Now.ToString() + "; unable to determine planetary hour."), conf); } else { try { if (conf.Fx.IconSet.Equals("Silver") && pHours.CurrentHour() == PlanetaryHours.Planet.Saturn) { trayIcon.Icon = conf.Fx.GlyphIconSmall("Tray.Saturn"); } else { trayIcon.Icon = conf.Fx.GlyphIconSmall(pHours.CurrentEnglishHour()); } string stat; switch (conf.Caption) { default: case Config.CaptionType.HourNumber: stat = pHours.HourOfDay(DateTime.Now); break; case Config.CaptionType.HouseOfMoment: stat = pHours.HouseOfMoment(DateTime.Now); break; case Config.CaptionType.LunarPhase: int i = localPhases.PhaseNum(DateTime.UtcNow); if (i == -1) { i = 7; } stat = conf.GetString(LunarPhase.PhaseName[i]); break; } string s = pHours.DayString() + "\r\n" + pHours.CurrentHourString() + "\r\n" + stat; // Too bad we're limited to 64 chars, because this would be nice... //string s = pHours.DayString() + ", " + pHours.CurrentHourString() + "\r\n" + // pHours.HourOfDay(DateTime.Now) + ", " + pHours.HouseOfMoment(DateTime.Now) + "\r\n" + // localPhases.PhaseNum(DateTime.UtcNow); if (s.Length >= 64) { s = s.Remove(60, s.Length - 60) + "..."; } trayIcon.Text = s; } catch (Exception ex) { trayIcon.Icon = new Icon(conf.Fx.ResourceStream("Exclamation.ico")); ErrorMessage("Unable to set glyph icon. [CurrentEnglishHour=" + pHours.CurrentEnglishHour() + "]", ex); } } }
private int printDiary(DateTime when, System.Drawing.Printing.PrintPageEventArgs e, int curpg, int pgtotal) { PlanetaryHours pHours = new PlanetaryHours(when, where, conf); Font hdfont = new Font(Font.Name, 15.0F, FontStyle.Bold); Font sfont = new Font(Font.Name, 11.0F); Font hrfont = new Font(Font.Name, 10.0F); Font hrhdfont = new Font(Font.Name, 11.0F, FontStyle.Bold); float x, y; bool hdrPrinted = false; if (printHr == 0) { displayHr = 0; hdrPrinted = true; float picx = e.MarginBounds.Left; Image im = Image.FromStream(conf.Fx.GlyphGif(pHours.EnglishDay())); x = picx + im.Width + 11; y = e.MarginBounds.Top; e.Graphics.DrawString(pHours.DayString(), hdfont, Brushes.Black, x, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(pHours.DayString(), hdfont, new PointF(x, y), StringFormat.GenericDefault).Height; string whenwhere = when.ToLongDateString() + " - " + where.Name; e.Graphics.DrawString(whenwhere, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(whenwhere, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2; string risetext, settext; if (!pHours.RS.SunRises) { risetext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"), conf.Res.GetString("Rise"), when.ToShortDateString(), where.Name); } else { risetext = String.Format(conf.Res.GetString("Calendar.labelSunrise"), conf.FormatTime(pHours.Hours[0].StartTime), where.UseSystemTime ? "" : (" " + where.ZoneAbbreviation)); } if (!pHours.RS.SunSets) { settext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"), conf.Res.GetString("Set"), when.ToShortDateString(), where.Name); } else { settext = String.Format(conf.Res.GetString("Calendar.labelSunset"), conf.FormatTime(pHours.Hours[12].StartTime), where.UseSystemTime ? "": (" " + where.ZoneAbbreviation)); } string riseset = risetext + " - " + settext; e.Graphics.DrawString(riseset, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(riseset, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2; float picy = e.MarginBounds.Top + (((y - e.MarginBounds.Top) - im.Height) / 2); if (y < (e.MarginBounds.Top + im.Height)) { y = picy + im.Height + 5; } e.Graphics.DrawImage(im, picx, picy); x = e.MarginBounds.Left; y += 11; e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y); y += 33; } else { x = e.MarginBounds.Left; y = e.MarginBounds.Top; string str = String.Format("{0} - {1} - {2}", pHours.DayString(), when.ToLongDateString(), where.Name); e.Graphics.DrawString(str, hrhdfont, Brushes.Black, x, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(str, hrhdfont, new PointF(x, y), StringFormat.GenericDefault).Height + 22; } float ght = hrfont.Height * 4; if (!hdrPrinted) { ght += hrfont.Height / 2; } TimeSpan os = new TimeSpan(0, 0, 1); while ((y + ght) <= e.MarginBounds.Bottom && printHr != 24) { if (inBounds(pHours.Hours[printHr].StartTime)) { displayHr++; PlanetaryHours.Planet pl = pHours.Hours[printHr].Hour; string displaystr = pHours.HourString(pl) + " ("; if (printHr == 0) { displaystr += conf.GetString("Sunrise") + ", "; } else if (printHr == 12) { displaystr += conf.GetString("Sunset") + ", "; } displaystr += conf.FormatTime(pHours.Hours[printHr].StartTime) + " - " + conf.FormatTime(pHours.Hours[printHr + 1].StartTime.Subtract(os)) + ")"; e.Graphics.DrawString(displaystr, hrfont, Brushes.Black, x, y, StringFormat.GenericDefault); float incr = e.Graphics.MeasureString(pHours.PlanetName(pl), hrfont, new PointF(x, y), StringFormat.GenericDefault).Height; y += (incr * 2); if (conf.PrintGlyphs) { RectangleF rf = new RectangleF(x, y + 1, 16, 16); Image im = Image.FromStream(conf.Fx.GlyphIconAsStream(Color.Black, pHours.EnglishName(pl))); e.Graphics.DrawImage(im, rf); e.Graphics.DrawLine(Pens.Gray, x + im.Width + 7, y, x + e.MarginBounds.Width, y); y += incr; e.Graphics.DrawLine(Pens.Gray, x + im.Width + 7, y, x + e.MarginBounds.Width, y); y += incr; } else { e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y); y += incr; e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y); y += incr; } // The first page has a long header; if not printing the first page, compensate for the absense of this header if (hdrPrinted) { y += incr / 2; } } printHr++; } string ver = Config.FormatVersion(); SizeF vsz = e.Graphics.MeasureString(ver, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault); e.Graphics.DrawString(ver, hrfont, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom - vsz.Height, StringFormat.GenericDefault); // Try to calculate the number of pages. A better way to do this would instead be, before printing, creating an array of Graphics surfaces // with each page. When the page number is known, go back and write the "Page __ of __" to each surface. Then, BitBlt() the appropriate // Graphics surface to e.Graphics. I don't envision this algorithm will be innaccurate, but I think it might be possible, especially with the "wrong" // size paper. int pgs, hrs = 0; foreach (PlanetaryHours.PlanetaryHour ph in pHours.Hours) { if (inBounds(ph.StartTime)) { hrs++; } } if (pgtotal == 0) { if (printHr == 24) { pgs = pageNo; } else if (radioButtonPrintAll.Checked) { pgs = 24 / (printHr / pageNo); if ((printHr * pgs) < 24) { pgs++; } } else { if (hrs > 9) { pgs = (hrs - 9) / 11; if ((displayHr * pgs) + 9 < hrs) { pgs++; } pgs++; } else { pgs = 1; } } } else { pgs = pgtotal; } string pg = String.Format(conf.GetString("Print.PageOf"), pageNo, pgs); SizeF tdsz = e.Graphics.MeasureString(pg, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault); e.Graphics.DrawString(pg, hrfont, Brushes.Black, e.MarginBounds.Right - tdsz.Width, e.MarginBounds.Bottom - tdsz.Height, StringFormat.GenericDefault); if (pageNo != pageTotal) { e.HasMorePages = true; } if (printHr == 24 || hrs == displayHr) { printHr = 0; dayNo++; } return(pgs); }
private void printNormal(DateTime when, System.Drawing.Printing.PrintPageEventArgs e, int curpg, int pgtotal) { PlanetaryHours pHours = new PlanetaryHours(when, where, conf); Font hdfont = new Font(Font.Name, 15.0F, FontStyle.Bold); Font sfont = new Font(Font.Name, 11.0F); Font hrfont = new Font(Font.Name, 10.0F); Font hrhdfont = new Font(Font.Name, 11.0F, FontStyle.Bold); float picx = e.MarginBounds.Left; Image dyim = Image.FromStream(conf.Fx.GlyphGif(pHours.EnglishDay())); float x = picx + dyim.Width + 11; float y = e.MarginBounds.Top; // Previously we used no StringFormat in DrawString and MeasureString, which made text (mainly at the lower-left margin) not formatted correctly. // Thanks to a microsoft.public.dotnet.languages.csharp posting by Ron Allen, we now use StringFormat.GenericDefault e.Graphics.DrawString(pHours.DayString(), hdfont, Brushes.Black, x, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(pHours.DayString(), hdfont, new PointF(x, y), StringFormat.GenericDefault).Height; string whenwhere = when.ToLongDateString() + " - " + where.Name; e.Graphics.DrawString(whenwhere, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(whenwhere, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2; string risetext, settext; if (!pHours.RS.SunRises) //(!pHours.RiseSet.SunRises) { risetext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"), conf.Res.GetString("Rise"), when.ToShortDateString(), where.Name); } else { risetext = String.Format(conf.Res.GetString("Calendar.labelSunrise"), conf.FormatTime(pHours.Hours[0].StartTime), where.UseSystemTime ? "" : (" " + where.ZoneAbbreviation)); } if (!pHours.RS.SunSets) { settext = String.Format(conf.Res.GetString("Calendar.NoSunRiseSet"), conf.Res.GetString("Set"), when.ToShortDateString(), where.Name); } else { settext = String.Format(conf.Res.GetString("Calendar.labelSunset"), conf.FormatTime(pHours.Hours[12].StartTime), where.UseSystemTime ? "": (" " + where.ZoneAbbreviation)); } string riseset = risetext + " - " + settext; e.Graphics.DrawString(riseset, sfont, Brushes.Black, x + 1, y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(riseset, sfont, new PointF(x, y), StringFormat.GenericDefault).Height + 2; float picy = e.MarginBounds.Top + (((y - e.MarginBounds.Top) - dyim.Height) / 2); if (y < (e.MarginBounds.Top + dyim.Height)) { y = picy + dyim.Height + 5; } e.Graphics.DrawImage(dyim, picx, picy); x = e.MarginBounds.Left; y += 11; e.Graphics.DrawLine(Pens.Gray, x, y, x + e.MarginBounds.Width, y); y += 22; e.Graphics.DrawString(conf.Res.GetString("Calendar.DayHours"), hrhdfont, Brushes.Black, x, y, StringFormat.GenericDefault); e.Graphics.DrawString(conf.Res.GetString("Calendar.NightHours"), hrhdfont, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width / 2), y, StringFormat.GenericDefault); y += e.Graphics.MeasureString(conf.Res.GetString("Calendar.DayHours"), hrhdfont, new PointF(x, y), StringFormat.GenericDefault).Height + 9; float savey = y; for (int hr = 0; hr < 24; hr++) { if (hr == 12) { y = savey; x = e.MarginBounds.Left + (e.MarginBounds.Width / 2); } PlanetaryHours.Planet pl = pHours.Hours[hr].Hour; RectangleF rf = new RectangleF(x, y, 16, 16); Image im; if (conf.PrintGlyphs) { im = Image.FromStream(conf.Fx.GlyphIconAsStream(Color.Black, pHours.EnglishName(pl))); e.Graphics.DrawImage(im, rf); } else { im = new Bitmap(1, 1); } e.Graphics.DrawString(pHours.PlanetName(pl), hrfont, Brushes.Black, x + (conf.PrintGlyphs ? im.Width + 5 : 0), y, StringFormat.GenericDefault); e.Graphics.DrawString(conf.FormatTime(pHours.Hours[hr].StartTime), hrfont, Brushes.Black, x + 112, y, StringFormat.GenericDefault); if (conf.PrintGlyphs) { y += im.Height + 5; } else { y += e.Graphics.MeasureString(pHours.PlanetName(pl), hrfont, new PointF(x, y), StringFormat.GenericDefault).Height; } } string ver = Config.FormatVersion(); SizeF vsz = e.Graphics.MeasureString(ver, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault); e.Graphics.DrawString(ver, hrfont, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom - vsz.Height, StringFormat.GenericDefault); string pg = String.Format(conf.GetString("Print.PageOf"), curpg, pgtotal); SizeF tdsz = e.Graphics.MeasureString(pg, hrfont, e.MarginBounds.Width, StringFormat.GenericDefault); e.Graphics.DrawString(pg, hrfont, Brushes.Black, e.MarginBounds.Right - tdsz.Width, e.MarginBounds.Bottom - tdsz.Height, StringFormat.GenericDefault); if (curpg != pgtotal) { e.HasMorePages = true; } dayNo++; }