home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / oletutor.pak / OWLOLE1.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  13KB  |  547 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Ole tutorial application -- owlole1.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/owlpch.h>
  6. #include <owl/applicat.h>
  7. #include <owl/decframe.h>
  8. #include <owl/dc.h>
  9. #include <owl/inputdia.h>
  10. #include <owl/opensave.h>
  11. #include <owl/controlb.h>
  12. #include <owl/buttonga.h>
  13. #include <owl/statusba.h>
  14. #include <owl/gdiobjec.h>
  15. #include <owl/chooseco.h>
  16. #include <classlib/arrays.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "owlole1.rc"
  20.  
  21. #define DocExt   "sp1"  // Scribble Pad #1 document extension
  22.  
  23. //----------------------------------------------------------------------------
  24.  
  25. typedef TArray<TPoint> TPoints;
  26. typedef TArrayIterator<TPoint> TPointsIterator;
  27.  
  28. class TLine : public TPoints {
  29.   public:
  30.     // Constructor to allow construction from a color and a pen size.
  31.     // Also serves as default constructor.
  32.     TLine(const TColor& color = TColor(0), int penSize = 1) :
  33.       TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
  34.  
  35.     // Functions to modify and query pen attributes.
  36.     int QueryPenSize() const
  37.     {
  38.       return PenSize;
  39.     }
  40.  
  41.     TColor& QueryColor()
  42.     {
  43.       return Color;
  44.     }
  45.  
  46.     void SetPen(TColor& newColor, int penSize = 0);
  47.     void SetPen(int penSize);
  48.  
  49.     // TLine draws itself.  Returns true if everything went OK.
  50.     virtual bool Draw(TDC&) const;
  51.  
  52.     // The == operator must be defined for the container class, even if unused
  53.     bool operator ==(const TLine& other) const
  54.     {
  55.       return &other == this;
  56.     }
  57.  
  58.     friend ostream& operator <<(ostream& os, const TLine& line);
  59.     friend istream& operator >>(istream& is, TLine& line);
  60.  
  61.   protected:
  62.     int PenSize;
  63.     TColor Color;
  64. };
  65.  
  66. void
  67. TLine::SetPen(int penSize)
  68. {
  69.   if (penSize < 1)
  70.     PenSize = 1;
  71.   else
  72.     PenSize = penSize;
  73. }
  74.  
  75. void
  76. TLine::SetPen(TColor& newColor, int penSize)
  77. {
  78.   // If penSize isn't the default (0), set PenSize to the new size.
  79.   if (penSize)
  80.     PenSize = penSize;
  81.  
  82.   Color = newColor;
  83. }
  84.  
  85. bool
  86. TLine::Draw(TDC& dc) const
  87. {
  88.   // Set pen for the dc to the values for this line
  89.   TPen pen(Color, PenSize);
  90.   dc.SelectObject(pen);
  91.  
  92.   // Iterates through the points in the line i.
  93.   TPointsIterator j(*this);
  94.   bool first = true;
  95.  
  96.   while (j) {
  97.     TPoint p = j++;
  98.  
  99.     if (!first)
  100.       dc.LineTo(p);
  101.     else {
  102.       dc.MoveTo(p);
  103.       first = false;
  104.     }
  105.   }
  106.   dc.RestorePen();
  107.   return true;
  108. }
  109.  
  110. ostream&
  111. operator <<(ostream& os, const TLine& line)
  112. {
  113.   // Write the number of points in the line
  114.   os << line.GetItemsInContainer();
  115.  
  116.   // Get and write pen attributes.
  117.   os << ' ' << line.Color << ' ' << line.PenSize;
  118.  
  119.   // Get an iterator for the array of points
  120.   TPointsIterator j(line);
  121.  
  122.   // While the iterator is valid (i.e. we haven't run out of points)
  123.   while(j)
  124.     // Write the point from the iterator and increment the array.
  125.     os << j++;
  126.   os << '\n';
  127.  
  128.   // return the stream object
  129.   return os;
  130. }
  131.  
  132. istream&
  133. operator >>(istream& is, TLine& line)
  134. {
  135.   unsigned numPoints;
  136.   is >> numPoints;
  137.  
  138.   COLORREF color;
  139.   int penSize;
  140.   is >> color >> penSize;
  141.   line.SetPen(TColor(color), penSize);
  142.  
  143.   while (numPoints--) {
  144.     TPoint point;
  145.     is >> point;
  146.     line.Add(point);
  147.   }
  148.  
  149.   // return the stream object
  150.   return is;
  151. }
  152.  
  153. //----------------------------------------------------------------------------
  154.  
  155. typedef TArray<TLine> TLines;
  156. typedef TArrayIterator<TLine> TLinesIterator;
  157.  
  158. class TScribbleWindow : public TWindow {
  159.   public:
  160.     TScribbleWindow(TWindow* parent, TOpenSaveDialog::TData& fileData);
  161.    ~TScribbleWindow()
  162.     {
  163.       delete DragDC;
  164.       delete Line;
  165.       delete Lines;
  166.     }
  167.  
  168.   protected:
  169.     TDC* DragDC;
  170.     TPen* Pen;
  171.     TLines* Lines;
  172.     TLine* Line; // To hold a single line at a time that later gets
  173.                  // stuck in Lines
  174.     TOpenSaveDialog::TData& FileData;
  175.     bool IsDirty, IsNewFile;
  176.  
  177.     void GetPenSize(); // GetPenSize always calls Line->SetPen().
  178.  
  179.     // Override member function of TWindow
  180.     void SetupWindow();
  181.     bool CanClose();
  182.  
  183.     // Message response functions
  184.     void EvLButtonDown(uint, TPoint&);
  185.     void EvRButtonDown(uint, TPoint&);
  186.     void EvMouseMove(uint, TPoint&);
  187.     void EvLButtonUp(uint, TPoint&);
  188.     void Paint(TDC&, bool, TRect&);
  189.     void CmFileNew();
  190.     void CmFileOpen();
  191.     void CmFileSave();
  192.     void CmFileSaveAs();
  193.     void CmPenSize();
  194.     void CmPenColor();
  195.     void CmAbout();
  196.     void SaveFile(bool pathChanged);
  197.     void OpenFile();
  198.  
  199.   DECLARE_RESPONSE_TABLE(TScribbleWindow);
  200. };
  201.  
  202. DEFINE_RESPONSE_TABLE1(TScribbleWindow, TWindow)
  203.   EV_WM_LBUTTONDOWN,
  204.   EV_WM_RBUTTONDOWN,
  205.   EV_WM_MOUSEMOVE,
  206.   EV_WM_LBUTTONUP,
  207.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  208.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  209.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  210.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  211.   EV_COMMAND(CM_ABOUT, CmAbout),
  212. END_RESPONSE_TABLE;
  213.  
  214. TScribbleWindow::TScribbleWindow(TWindow* parent, TOpenSaveDialog::TData& fileData)
  215. :
  216.   TWindow(parent, 0),
  217.   FileData(fileData)
  218. {
  219.   DragDC    = 0;
  220.   Lines     = new TLines(5, 0, 5);
  221.   Line      = new TLine(TColor::Black, 1);
  222.   Pen       = 0;
  223.   IsNewFile = true;
  224.   IsDirty   = false;
  225. }
  226.  
  227. void
  228. TScribbleWindow::SetupWindow()
  229. {
  230.   TWindow::SetupWindow();
  231.   if (*FileData.FileName)
  232.     OpenFile();
  233.   else
  234.     SetDocTitle("Untitled", 0);
  235. }
  236.  
  237. bool
  238. TScribbleWindow::CanClose()
  239. {
  240.   if (IsDirty)
  241.     switch (MessageBox("Do you want to save?", "Scribbling has changed",
  242.                        MB_YESNOCANCEL | MB_ICONQUESTION)) {
  243.       case IDCANCEL:
  244.         // Choosing Cancel means to abort the close -- return false.
  245.         return false;
  246.  
  247.       case IDYES:
  248.         // Choosing Yes means to save the drawing, then close.
  249.         CmFileSave();
  250.     }
  251.   return true;
  252. }
  253.  
  254. void
  255. TScribbleWindow::EvLButtonDown(uint, TPoint& point)
  256. {
  257.   if (!DragDC) {
  258.     SetCapture();
  259.     DragDC = new TClientDC(*this);
  260.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  261.     DragDC->SelectObject(*Pen);
  262.     DragDC->MoveTo(point);
  263.     Line->Add(point);
  264.     IsDirty = true;
  265.   }
  266. }
  267.  
  268. void
  269. TScribbleWindow::EvRButtonDown(uint, TPoint&)
  270. {
  271.   GetPenSize();
  272. }
  273.  
  274. void
  275. TScribbleWindow::EvMouseMove(uint, TPoint& point)
  276. {
  277.   if (DragDC) {
  278.     DragDC->LineTo(point);
  279.     Line->Add(point);
  280.   }
  281. }
  282.  
  283. void
  284. TScribbleWindow::EvLButtonUp(uint, TPoint&)
  285. {
  286.   if (DragDC) {
  287.     ReleaseCapture();
  288.     Lines->Add(*Line);
  289.     Line->Flush();
  290.     delete DragDC;
  291.     delete Pen;
  292.     DragDC = 0;
  293.   }
  294. }
  295.  
  296. void
  297. TScribbleWindow::CmPenSize()
  298. {
  299.   GetPenSize();
  300. }
  301.  
  302. void
  303. TScribbleWindow::CmPenColor()
  304. {
  305.   TChooseColorDialog::TData colors;
  306.   static TColor custColors[16] = {
  307.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  308.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  309.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  310.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  311.   };
  312.  
  313.   colors.Flags = CC_RGBINIT;
  314.   colors.Color = TColor(Line->QueryColor());
  315.   colors.CustColors = custColors;
  316.   if (TChooseColorDialog(this, colors).Execute() == IDOK)
  317.     Line->SetPen(colors.Color);
  318. }
  319.  
  320. void
  321. TScribbleWindow::GetPenSize()
  322. {
  323.   char inputText[6];
  324.   int penSize = Line->QueryPenSize();
  325.  
  326.   wsprintf(inputText, "%d", penSize);
  327.   if (TInputDialog(this, "Line Thickness",
  328.                    "Input a new thickness:",
  329.                    inputText,
  330.                    sizeof(inputText)).Execute() == IDOK) {
  331.     penSize = atoi(inputText);
  332.  
  333.     if (penSize < 1)
  334.       penSize = 1;
  335.   }
  336.   Line->SetPen(penSize);
  337. }
  338.  
  339. void
  340. TScribbleWindow::Paint(TDC& dc, bool, TRect&)
  341. {
  342.   // Iterates through the array of line objects.
  343.   TLinesIterator i(*Lines);
  344.  
  345.   while (i)
  346.     i++.Draw(dc);
  347. }
  348.  
  349. void
  350. TScribbleWindow::CmFileSave()
  351. {
  352.   if (IsNewFile)
  353.     CmFileSaveAs();
  354.   else
  355.     SaveFile(false);
  356. }
  357.  
  358. void
  359. TScribbleWindow::CmFileSaveAs()
  360. {
  361.   if (TFileSaveDialog(this, FileData).Execute() == IDOK)
  362.     SaveFile(true);
  363. }
  364.  
  365. void
  366. TScribbleWindow::CmAbout()
  367. {
  368.   TDialog(this, IDD_ABOUT).Execute();
  369. }
  370.  
  371. void
  372. TScribbleWindow::SaveFile(bool pathChanged)
  373. {
  374.   ofstream os(FileData.FileName);
  375.  
  376.   if (!os)
  377.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  378.   else {
  379.     // Write the number of lines in the figure
  380.     os << Lines->GetItemsInContainer();
  381.  
  382.     // Append a description using a resource string
  383.     os << ' ' << string(*GetApplication(), IDS_FILEINFO) << '\n';
  384.  
  385.     // Get an iterator for the array of lines
  386.     TLinesIterator i(*Lines);
  387.  
  388.     // While the iterator is valid (i.e. we haven't run out of lines)
  389.     while (i)
  390.       // Copy the current line from the iterator and increment the array.
  391.       os << i++;
  392.  
  393.     // Set new file and dirty display indicator to false.
  394.     IsNewFile = IsDirty = false;
  395.     if (pathChanged)
  396.       SetDocTitle(FileData.FileName, 0);
  397.   }
  398. }
  399.  
  400. void
  401. TScribbleWindow::OpenFile()
  402. {
  403.   ifstream is(FileData.FileName);
  404.  
  405.   if (!is)
  406.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  407.   else {
  408.     unsigned numLines;
  409.     char fileinfo[100];
  410.  
  411.     Lines->Flush();
  412.     Line->Flush();
  413.  
  414.     is >> numLines;
  415.     is.getline(fileinfo, sizeof(fileinfo));
  416.     SetDocTitle(FileData.FileName, 0);
  417.  
  418.     for (int i = 0; i < numLines; i++) {
  419.       TLine line;
  420.       is >> line;
  421.       Lines->Add(line);
  422.     }
  423.   }
  424.   IsNewFile = IsDirty = false;
  425.   Invalidate();
  426. }
  427.  
  428. //----------------------------------------------------------------------------
  429.  
  430. class TScribbleApp : public TApplication {
  431.   public:
  432.     TScribbleApp();
  433.  
  434.   protected:
  435.     void InitMainWindow();
  436.     void InitInstance();
  437.  
  438.     void CmFileNew();
  439.     void CmFileOpen();
  440.  
  441.     TOpenSaveDialog::TData FileData;
  442.  
  443.   DECLARE_RESPONSE_TABLE(TScribbleApp);
  444. };
  445.  
  446. DEFINE_RESPONSE_TABLE(TScribbleApp)
  447.   EV_COMMAND(CM_FILENEW, CmFileNew),
  448.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  449. END_RESPONSE_TABLE;
  450.  
  451. TScribbleApp::TScribbleApp()
  452. :
  453.   TApplication("Scribble Pad"),
  454.   FileData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  455.            "Scribble Files (*."DocExt")|*."DocExt"|", 0, "", DocExt)
  456. {
  457. }
  458.  
  459. void
  460. TScribbleApp::InitMainWindow()
  461. {
  462.   // Construct the decorated frame window
  463.   TDecoratedFrame* frame = new TDecoratedFrame(0, GetName(), 0, true, this);
  464.  
  465.   // Construct a status bar
  466.   TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  467.  
  468.   // Construct a control bar
  469.   TControlBar* cb = new TControlBar(frame);
  470.   cb->Insert(*new TButtonGadget(CM_FILENEW, CM_FILENEW, TButtonGadget::Command));
  471.   cb->Insert(*new TButtonGadget(CM_FILEOPEN, CM_FILEOPEN, TButtonGadget::Command));
  472.   cb->Insert(*new TButtonGadget(CM_FILESAVE, CM_FILESAVE, TButtonGadget::Command));
  473.   cb->Insert(*new TButtonGadget(CM_FILESAVEAS, CM_FILESAVEAS, TButtonGadget::Command));
  474.   cb->Insert(*new TSeparatorGadget);
  475.   cb->Insert(*new TButtonGadget(CM_PENSIZE, CM_PENSIZE, TButtonGadget::Command));
  476.   cb->Insert(*new TButtonGadget(CM_PENCOLOR, CM_PENCOLOR, TButtonGadget::Command));
  477.   cb->Insert(*new TSeparatorGadget);
  478.   cb->Insert(*new TButtonGadget(CM_ABOUT, CM_ABOUT, TButtonGadget::Command));
  479.   cb->Attr.Id = IDW_TOOLBAR;
  480.  
  481.   // Insert the status bar and control bar into the frame
  482.   frame->Insert(*sb, TDecoratedFrame::Bottom);
  483.   frame->Insert(*cb, TDecoratedFrame::Top);
  484.  
  485.   // Set the main window and its menu
  486.   SetMainWindow(frame);
  487.   GetMainWindow()->SetMenuDescr(TMenuDescr(IDM_SCRIBBLE));
  488. }
  489.  
  490. //
  491. // Call file new command handler to get the initial new window
  492. //
  493. void
  494. TScribbleApp::InitInstance()
  495. {
  496.   TApplication::InitInstance();
  497.  
  498.   FileData.FileName[0] = 0;
  499.   TWindow* client = new TScribbleWindow(0, FileData);
  500.   TWindow* oldClient = GetMainWindow()->SetClientWindow(client);
  501.   if (oldClient) {
  502.     oldClient->Destroy();
  503.     delete oldClient;
  504.   }
  505. }
  506.  
  507. void
  508. TScribbleApp::CmFileNew()
  509. {
  510.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  511.   if (!scribbleWindow->CanClose())
  512.     return;
  513.  
  514.   FileData.FileName[0] = 0;
  515.   TWindow* client = new TScribbleWindow(0, FileData);
  516.   GetMainWindow()->SetClientWindow(client);
  517.   scribbleWindow->Destroy(0);
  518.   delete scribbleWindow;
  519. }
  520.  
  521. void
  522. TScribbleApp::CmFileOpen()
  523. {
  524.   TWindow* scribbleWindow = GetMainWindow()->GetClientWindow();
  525.   if (!scribbleWindow->CanClose())
  526.     return;
  527.  
  528.   if (TFileOpenDialog(GetMainWindow(), FileData).Execute() == IDOK) {
  529.     TWindow* newScribbleWindow = new TScribbleWindow(0, FileData);
  530.     GetMainWindow()->SetClientWindow(newScribbleWindow);
  531.     scribbleWindow->Destroy(0);
  532.     delete scribbleWindow;
  533.   }
  534. }
  535.  
  536. int
  537. OwlMain(int /*argc*/, char* /*argv*/ [])
  538. {
  539.   try {
  540.     return TScribbleApp().Run();
  541.   }
  542.   catch (xmsg& x) {
  543.     ::MessageBox(0, x.why().c_str(), "Scribble App Exception", MB_OK);
  544.   }
  545.   return -1;
  546. }
  547.