home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / msmqocm.cab / DRAWDLG.CPP < prev    next >
C/C++ Source or Header  |  1997-10-06  |  14KB  |  565 lines

  1. // drawdlg.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "disdraw.h"
  6. #include "drawdlg.h"
  7.  
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13.  
  14. #define MAX_FORMAT_NAME_LEN 256
  15.  
  16. //
  17. // Distributed draw queue type
  18. //
  19. CLSID guidDrawType =
  20. { 0x151ceac0, 0xacb5, 0x11cf, { 0x8b, 0x51, 0x00, 0x20, 0xaf, 0x92, 0x95, 0x46 } };
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CDisdrawDlg dialog
  24.  
  25. CDisdrawDlg::CDisdrawDlg(CWnd* pParent /*=NULL*/)
  26.     : CDialog(CDisdrawDlg::IDD, pParent)
  27. {
  28.     //{{AFX_DATA_INIT(CDisdrawDlg)
  29.     m_strFriend = _T("");
  30.     m_iDelivery = 0;
  31.     //}}AFX_DATA_INIT
  32.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  33.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  34. }
  35.  
  36. void CDisdrawDlg::DoDataExchange(CDataExchange* pDX)
  37. {
  38.     CDialog::DoDataExchange(pDX);
  39.     //{{AFX_DATA_MAP(CDisdrawDlg)
  40.     DDX_Control(pDX, IDC_DRAWAREA_SCRIBLLE, m_drawScribble);
  41.     DDX_Control(pDX, IDC_BUTTON_ATTACH, m_btnAttach);
  42.     DDX_Text(pDX, IDC_EDIT_FRIEND, m_strFriend);
  43.     DDX_Radio(pDX, IDC_RADIO_EXPRESS, m_iDelivery);
  44.     //}}AFX_DATA_MAP
  45. }
  46.  
  47. BEGIN_MESSAGE_MAP(CDisdrawDlg, CDialog)
  48.     //{{AFX_MSG_MAP(CDisdrawDlg)
  49.     ON_WM_PAINT()
  50.     ON_WM_QUERYDRAGICON()
  51.     ON_BN_CLICKED(IDC_BUTTON_ATTACH, OnButtonAttach)
  52.     ON_EN_CHANGE(IDC_EDIT_FRIEND, OnChangeEditFriend)
  53.     ON_WM_CLOSE()
  54.     //}}AFX_MSG_MAP
  55. END_MESSAGE_MAP()
  56.  
  57. /////////////////////////////////////////////////////////////////////////////
  58. // CDisdrawDlg message handlers
  59.  
  60.  
  61. BOOL LocateQueue(CString m_strLabel, WCHAR *wcsFormatName, DWORD dwNumChars)
  62. {
  63.     //
  64.     // Set restrictions to locate the draw queue with the specified label
  65.     //
  66.     DWORD cProps = 0;
  67.     MQPROPERTYRESTRICTION aPropRestriction[2];
  68.     MQRESTRICTION Restriction;
  69.  
  70.     aPropRestriction[cProps].rel           = PREQ;
  71.     aPropRestriction[cProps].prop          = PROPID_Q_TYPE;
  72.     aPropRestriction[cProps].prval.vt      = VT_CLSID;
  73.     aPropRestriction[cProps].prval.puuid   = &guidDrawType;
  74.     cProps++;
  75.  
  76.     WCHAR wcsLabel[MQ_MAX_Q_LABEL_LEN];
  77.     mbstowcs(wcsLabel, m_strLabel, MQ_MAX_Q_LABEL_LEN);
  78.     aPropRestriction[cProps].rel           = PREQ;
  79.     aPropRestriction[cProps].prop          = PROPID_Q_LABEL;
  80.     aPropRestriction[cProps].prval.vt      = VT_LPWSTR;
  81.     aPropRestriction[cProps].prval.pwszVal = wcsLabel;
  82.     cProps++;
  83.  
  84.     Restriction.cRes = cProps;
  85.     Restriction.paPropRes = aPropRestriction;
  86.  
  87.  
  88.     //
  89.     // Request the queue instance for the specified queue
  90.     //
  91.     cProps = 0;
  92.     QUEUEPROPID aPropId[1];
  93.     MQCOLUMNSET Column;
  94.     
  95.     aPropId[cProps] = PROPID_Q_INSTANCE;
  96.     cProps++;
  97.  
  98.     Column.cCol = cProps;
  99.     Column.aCol = aPropId;
  100.  
  101.  
  102.     //
  103.     // Locate the specified queue
  104.     //
  105.     HANDLE hEnum;
  106.     BOOL fFound = FALSE;
  107.     HRESULT hr = MQLocateBegin(NULL, &Restriction, &Column, NULL, &hEnum);
  108.     if (!FAILED(hr))
  109.     {
  110.         MQPROPVARIANT aPropVar[1];
  111.         DWORD cQueue = 1;
  112.         hr = MQLocateNext(hEnum, &cQueue, aPropVar);
  113.         if (!FAILED(hr) && cQueue > 0)
  114.         {
  115.             //
  116.             // Obtain the format name for the located queue
  117.             //
  118.             hr = MQInstanceToFormatName(aPropVar[0].puuid, wcsFormatName, &dwNumChars);
  119.             MQFreeMemory(aPropVar[0].puuid);
  120.             if (!FAILED(hr))
  121.                 fFound = TRUE;
  122.         }
  123.  
  124.         MQLocateEnd(hEnum);
  125.     }
  126.  
  127.  
  128.     return fFound;
  129. }
  130.  
  131.  
  132. BOOL CDisdrawDlg::OpenReceiveQueue()
  133. {
  134.     //
  135.     // Do not create the receiving queue if it already exists in the enterprise
  136.     //
  137.     HRESULT hr;
  138.     WCHAR wcsFormatName[MAX_FORMAT_NAME_LEN];
  139.     if (!LocateQueue(m_strLogin, wcsFormatName, MAX_FORMAT_NAME_LEN))
  140.     {
  141.         //
  142.         // Form the pathname to the receiving queue
  143.         //
  144.         char mbsPathName[MQ_MAX_Q_NAME_LEN];
  145.         DWORD dwNumChars = MQ_MAX_Q_NAME_LEN;
  146.         GetComputerName(mbsPathName, &dwNumChars);
  147.         strcat(mbsPathName, "\\");
  148.         strcat(mbsPathName, m_strLogin);
  149.  
  150.  
  151.         //
  152.         // Prepare the receiving queue properties
  153.         //
  154.         DWORD cProps = 0;
  155.         QUEUEPROPID  aPropId[3];
  156.         MQPROPVARIANT aPropVar[3];
  157.         MQQUEUEPROPS propsQueue;
  158.         
  159.         WCHAR wcsPathName[MQ_MAX_Q_NAME_LEN];
  160.         mbstowcs(wcsPathName, mbsPathName, MQ_MAX_Q_NAME_LEN);
  161.         aPropId[cProps]             = PROPID_Q_PATHNAME;
  162.         aPropVar[cProps].vt         = VT_LPWSTR;
  163.         aPropVar[cProps].pwszVal = wcsPathName;
  164.         cProps++;
  165.  
  166.         aPropId[cProps]             = PROPID_Q_TYPE;
  167.         aPropVar[cProps].vt         = VT_CLSID;
  168.         aPropVar[cProps].puuid     = &guidDrawType;
  169.         cProps++;
  170.  
  171.         WCHAR wcsLabel[MQ_MAX_Q_LABEL_LEN];
  172.         mbstowcs(wcsLabel, m_strLogin, MQ_MAX_Q_LABEL_LEN);
  173.         aPropId[cProps]             = PROPID_Q_LABEL;
  174.         aPropVar[cProps].vt         = VT_LPWSTR;
  175.         aPropVar[cProps].pwszVal = wcsLabel;
  176.         cProps++;
  177.  
  178.         propsQueue.cProp    = cProps;
  179.         propsQueue.aPropID    = aPropId;
  180.         propsQueue.aPropVar = aPropVar;
  181.         propsQueue.aStatus    = NULL;
  182.  
  183.  
  184.         //
  185.         // Create the receiving queue
  186.         //
  187.         dwNumChars = MAX_FORMAT_NAME_LEN;
  188.         hr = MQCreateQueue(NULL, &propsQueue, wcsFormatName, &dwNumChars);    
  189.  
  190.  
  191.         //
  192.         // If the receiving queue already exists, obtain its format name
  193.         //
  194.         if (hr == MQ_ERROR_QUEUE_EXISTS)
  195.             hr = MQPathNameToFormatName(wcsPathName, wcsFormatName, &dwNumChars);
  196.  
  197.         if (FAILED(hr))
  198.             return FALSE;
  199.     }
  200.  
  201.     //
  202.     // Open the receiving queue (may need to retry due to replication latency)
  203.     //
  204.     while ((hr = MQOpenQueue(wcsFormatName, 
  205.                              MQ_RECEIVE_ACCESS, 
  206.                              0, &m_hqIncoming)) == MQ_ERROR_QUEUE_NOT_FOUND)
  207.         Sleep (500);
  208.  
  209.     if (FAILED(hr))
  210.         return FALSE;
  211.  
  212.  
  213.     return TRUE;
  214. }
  215.  
  216.  
  217. DWORD ReceiveUpdates(CDisdrawDlg *pDrawDlg)
  218. {
  219.        //
  220.     // Prepare the message properties to receive
  221.     //
  222.     DWORD cProps = 0;
  223.     MQMSGPROPS    propsMessage;
  224.     MQPROPVARIANT aPropVar[2];
  225.     MSGPROPID     aPropId[2];
  226.  
  227.     WCHAR wcsBody[MAX_MSG_BODY_LEN];
  228.     aPropId[cProps]                = PROPID_M_BODY;
  229.     aPropVar[cProps].vt            = VT_UI1 | VT_VECTOR;
  230.     aPropVar[cProps].caub.cElems = sizeof(wcsBody);
  231.     aPropVar[cProps].caub.pElems = (UCHAR *)wcsBody;
  232.     cProps++;
  233.  
  234.     aPropId[cProps]                = PROPID_M_BODY_SIZE;
  235.     aPropVar[cProps].vt            = VT_UI4;
  236.     cProps++;
  237.  
  238.     propsMessage.cProp    = cProps;
  239.     propsMessage.aPropID  = aPropId;
  240.     propsMessage.aPropVar = aPropVar;
  241.     propsMessage.aStatus  = NULL;
  242.  
  243.  
  244.     //
  245.     // Keep receiving updates sent to the incoming queue
  246.     //
  247.     HRESULT hr;
  248.     LINE line;
  249.     char mbsBody[MAX_MSG_BODY_LEN + 1];
  250.  
  251.     while (TRUE)
  252.     {
  253.         //
  254.         // Synchronously receive a message from the incoming queue
  255.         //
  256.         hr = MQReceiveMessage(pDrawDlg->m_hqIncoming, INFINITE, 
  257.                               MQ_ACTION_RECEIVE, &propsMessage, 
  258.                               NULL, NULL, NULL, NULL);
  259.  
  260.         //
  261.         // Determine if the message contains a keystroke or a line
  262.         //
  263.         if (!FAILED(hr))
  264.         {
  265.             //
  266.             // Convert the body to a multi-byte null-terminated string 
  267.             //
  268.             UINT uNumChars = aPropVar[1].ulVal/sizeof(WCHAR);
  269.             wcstombs(mbsBody, wcsBody, uNumChars);
  270.             mbsBody[uNumChars] = '\0';
  271.  
  272.             //
  273.             // Add the keystroke to the drawing
  274.             //
  275.             if (uNumChars == 1)
  276.             {
  277.                 pDrawDlg->m_drawScribble.AddKeystroke(mbsBody);
  278.             }
  279.             
  280.             //
  281.             // Add the received line to the drawing
  282.             //
  283.             else
  284.             {
  285.                 sscanf(mbsBody, "%07ld%07ld%07ld%07ld", 
  286.                        &line.ptStart.x, &line.ptStart.y, 
  287.                        &line.ptEnd.x, &line.ptEnd.y);
  288.                 pDrawDlg->m_drawScribble.AddLine(line);
  289.             }
  290.         }
  291.     }
  292.  
  293.  
  294.     return 0;
  295. }
  296.  
  297.  
  298. BOOL CDisdrawDlg::OnInitDialog()
  299. {
  300.     CDialog::OnInitDialog();
  301.  
  302.     // Set the icon for this dialog.  The framework does this automatically
  303.     //  when the application's main window is not a dialog
  304.     SetIcon(m_hIcon, TRUE);            // Set big icon
  305.     SetIcon(m_hIcon, FALSE);        // Set small icon
  306.     
  307.     // TODO: Add extra initialization here
  308.     
  309.     //
  310.     // Display the login name in the window title
  311.     //
  312.     SetWindowText(m_strLogin);
  313.  
  314.  
  315.     //
  316.     // No queues are open yet
  317.     //
  318.     m_hqIncoming = NULL;
  319.     m_hqOutgoing = NULL;
  320.  
  321.  
  322.     //
  323.     // Open the receiving queue and receive incoming messages
  324.     //
  325.     DWORD dwThreadID;
  326.     if (OpenReceiveQueue())
  327.         CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveUpdates, this, 0,
  328.                      &dwThreadID);
  329.     else
  330.         AfxMessageBox("Cannot open receiving queue.");
  331.  
  332.  
  333.     return TRUE;  // return TRUE  unless you set the focus to a control
  334. }
  335.  
  336.  
  337. // If you add a minimize button to your dialog, you will need the code below
  338. //  to draw the icon.  For MFC applications using the document/view model,
  339. //  this is automatically done for you by the framework.
  340.  
  341. void CDisdrawDlg::OnPaint() 
  342. {
  343.     if (IsIconic())
  344.     {
  345.         CPaintDC dc(this); // device context for painting
  346.  
  347.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  348.  
  349.         // Center icon in client rectangle
  350.         int cxIcon = GetSystemMetrics(SM_CXICON);
  351.         int cyIcon = GetSystemMetrics(SM_CYICON);
  352.         CRect rect;
  353.         GetClientRect(&rect);
  354.         int x = (rect.Width() - cxIcon + 1) / 2;
  355.         int y = (rect.Height() - cyIcon + 1) / 2;
  356.  
  357.         // Draw the icon
  358.         dc.DrawIcon(x, y, m_hIcon);
  359.     }
  360.     else
  361.     {
  362.         CDialog::OnPaint();
  363.     }
  364. }
  365.  
  366.  
  367. // The system calls this to obtain the cursor to display while the user drags
  368. //  the minimized window.
  369. HCURSOR CDisdrawDlg::OnQueryDragIcon()
  370. {
  371.     return (HCURSOR) m_hIcon;
  372. }
  373.  
  374.  
  375. void CDisdrawDlg::SendKeystroke(UINT uChar)
  376. {
  377.     //
  378.     // Send the keystroke to the friend, if any
  379.     //
  380.     if (m_hqOutgoing != NULL)
  381.     {
  382.         //
  383.         // Prepare the message properties to send
  384.         //
  385.         DWORD cProps = 0;
  386.         MQMSGPROPS    propsMessage;
  387.         MQPROPVARIANT aPropVar[5];
  388.         MSGPROPID     aPropId[5];
  389.  
  390.         WCHAR wcsBody[1];
  391.         swprintf(wcsBody, L"%c", uChar); 
  392.         aPropId[cProps]                = PROPID_M_BODY;
  393.         aPropVar[cProps].vt            = VT_UI1 | VT_VECTOR;
  394.         aPropVar[cProps].caub.cElems = sizeof(wcsBody);
  395.         aPropVar[cProps].caub.pElems = (UCHAR *)wcsBody;
  396.         cProps++;
  397.  
  398.         WCHAR wcsLabel[MQ_MAX_MSG_LABEL_LEN];
  399.         swprintf(wcsLabel, L"Key: %c", uChar);
  400.         aPropId[cProps]                = PROPID_M_LABEL;
  401.         aPropVar[cProps].vt            = VT_LPWSTR;
  402.         aPropVar[cProps].pwszVal    = wcsLabel;
  403.         cProps++;
  404.  
  405.         UpdateData(TRUE);
  406.         aPropId[cProps]                = PROPID_M_DELIVERY;
  407.         aPropVar[cProps].vt            = VT_UI1;
  408.         aPropVar[cProps].bVal        = m_iDelivery;
  409.         cProps++;
  410.  
  411.         aPropId[cProps]                = PROPID_M_PRIORITY;
  412.         aPropVar[cProps].vt            = VT_UI1;
  413.         aPropVar[cProps].bVal        = 4;
  414.         cProps++;
  415.  
  416.         aPropId[cProps]                = PROPID_M_BODY_TYPE;
  417.         aPropVar[cProps].vt            = VT_UI4;
  418.         aPropVar[cProps].lVal        = (long)VT_BSTR;
  419.         cProps++;
  420.  
  421.         propsMessage.cProp    = cProps;
  422.         propsMessage.aPropID  = aPropId;
  423.         propsMessage.aPropVar = aPropVar;
  424.         propsMessage.aStatus  = NULL;
  425.  
  426.  
  427.         //
  428.         // Send the message to the outgoing queue
  429.         //
  430.         MQSendMessage(m_hqOutgoing, &propsMessage, NULL);
  431.     }
  432. }
  433.  
  434.  
  435. void CDisdrawDlg::SendMouseMovement(LINE line)
  436. {
  437.     //
  438.     // Send the line to the friend, if any
  439.     //
  440.     if (m_hqOutgoing != NULL)
  441.     {
  442.         //
  443.         // Prepare the message properties to send
  444.         //
  445.         DWORD cProps = 0;
  446.         MQMSGPROPS    propsMessage;
  447.         MQPROPVARIANT aPropVar[5];
  448.         MSGPROPID     aPropId[5];
  449.  
  450.         WCHAR wcsBody[MAX_MSG_BODY_LEN];
  451.         swprintf(wcsBody, L"%07ld%07ld%07ld%07ld", 
  452.                  line.ptStart.x, line.ptStart.y, line.ptEnd.x, line.ptEnd.y);
  453.         aPropId[cProps]                = PROPID_M_BODY;
  454.         aPropVar[cProps].vt            = VT_UI1 | VT_VECTOR;
  455.         aPropVar[cProps].caub.cElems = sizeof(wcsBody);
  456.         aPropVar[cProps].caub.pElems = (UCHAR *)wcsBody;
  457.         cProps++;
  458.  
  459.         WCHAR wcsLabel[MQ_MAX_MSG_LABEL_LEN];
  460.         swprintf(wcsLabel, L"%ld,%ld To %ld,%ld", 
  461.                  line.ptStart.x, line.ptStart.y, line.ptEnd.x, line.ptEnd.y);
  462.         aPropId[cProps]                = PROPID_M_LABEL;
  463.         aPropVar[cProps].vt            = VT_LPWSTR;
  464.         aPropVar[cProps].pwszVal    = wcsLabel;
  465.         cProps++;
  466.  
  467.         UpdateData(TRUE);
  468.         aPropId[cProps]                = PROPID_M_DELIVERY;
  469.         aPropVar[cProps].vt            = VT_UI1;
  470.         aPropVar[cProps].bVal        = m_iDelivery;
  471.         cProps++;
  472.  
  473.         aPropId[cProps]                = PROPID_M_PRIORITY;
  474.         aPropVar[cProps].vt            = VT_UI1;
  475.         aPropVar[cProps].bVal        = 3;
  476.         cProps++;
  477.  
  478.         aPropId[cProps]                = PROPID_M_BODY_TYPE;
  479.         aPropVar[cProps].vt            = VT_UI4;
  480.         aPropVar[cProps].lVal        = (long)VT_BSTR;
  481.         cProps++;
  482.  
  483.         propsMessage.cProp    = cProps;
  484.         propsMessage.aPropID  = aPropId;
  485.         propsMessage.aPropVar = aPropVar;
  486.         propsMessage.aStatus  = NULL;
  487.  
  488.  
  489.         //
  490.         // Send the message to the outgoing queue
  491.         //
  492.         MQSendMessage(m_hqOutgoing, &propsMessage, NULL);
  493.     }
  494. }
  495.  
  496.  
  497. void CDisdrawDlg::OnButtonAttach() 
  498. {
  499.     // TODO: Add your control notification handler code here
  500.  
  501.     //
  502.     // Obtain the name of the friend
  503.     //
  504.     UpdateData(TRUE);
  505.     m_strFriend.MakeUpper();
  506.  
  507.  
  508.     //
  509.     // Make sure the friend queue exists
  510.     //
  511.     WCHAR wcsFormatName[MAX_FORMAT_NAME_LEN];
  512.     if (!LocateQueue(m_strFriend, wcsFormatName, MAX_FORMAT_NAME_LEN))
  513.     {
  514.         AfxMessageBox("No such friend, sorry...");
  515.         return;
  516.     }
  517.  
  518.  
  519.     //
  520.     // Open the friend queue for sending
  521.     //
  522.     HANDLE hqNewFriend;
  523.     HRESULT hr = MQOpenQueue(wcsFormatName, MQ_SEND_ACCESS, 0, &hqNewFriend);
  524.     if (FAILED(hr))
  525.         AfxMessageBox("Cannot open friend queue.");
  526.  
  527.     else
  528.     {
  529.         //
  530.         // Close the previous friend and update the window title
  531.         //
  532.         if (m_hqOutgoing != NULL)
  533.             MQCloseQueue(m_hqOutgoing);
  534.         m_hqOutgoing = hqNewFriend;
  535.         CString strTitle = m_strLogin + " connected to " + m_strFriend;
  536.         SetWindowText(strTitle);
  537.         m_btnAttach.EnableWindow(FALSE);
  538.     }
  539. }
  540.  
  541.  
  542. void CDisdrawDlg::OnChangeEditFriend() 
  543. {
  544.     // TODO: Add your control notification handler code here
  545.  
  546.     m_btnAttach.EnableWindow(TRUE);
  547. }
  548.  
  549.  
  550. void CDisdrawDlg::OnClose() 
  551. {
  552.     // TODO: Add your message handler code here and/or call default
  553.  
  554.     //
  555.     // Close the open queues, if any
  556.     //
  557.     if (m_hqIncoming != NULL)
  558.         MQCloseQueue(m_hqIncoming);
  559.  
  560.     if (m_hqOutgoing != NULL)
  561.         MQCloseQueue(m_hqOutgoing);
  562.  
  563.     CDialog::OnClose();
  564. }
  565.