windows程序设计之STRPROG学习总结

任务定义:同一程序的多个实例共享一份数据,一个实例对数据的修改会影响到其他实例,具体到窗口中就是,一个实例中的数据显示变化引起其他各个实例中数据显示的更新。

整体分析:编写一个dll,其中包含被同一程序的不同实例共享的内存数据;类似于document-view模式,document对应dll中的共享内存数据,view对应各个实例的显示窗口;由此可以实现一个实例对共享数据的修改,可以影响到其他实例,每次修改后当前实例向所有其他实例发送一个消息,使得各个实例窗口数据同步更新。

关键代码分析:

1、共享数据段

// 创建名为shared的共享数据段

#pragma data_seg ("shared")    // 必须对数据初始化,否则编译器将把它们放在普通的未初始化数据段中

int   iTotal = 0 ;                  //标识字符串总数

WCHAR szStrings [MAX_STRINGS][MAX_LENGTH + 1] = { '\0' } ;  //关键共享字符串数组,用来在各个实例中显示

#pragma data_seg ()  

#pragma comment(linker,"/SECTION:shared,RWS")

2、各个应用程序实例中的字符串显示函数

BOOL CALLBACK GetStrCallBack (PTSTR pString, CBPARAM * pcbp)

{

    // 输出字符串

     TextOut (pcbp->hdc, pcbp->xText, pcbp->yText,

              pString, lstrlen (pString)) ;

     // 输出y坐标递增一个字符高度,并与窗口可输出最大行比较

     // 如果输出行已到最大行,则执行

     if ((pcbp->yText += pcbp->yIncr) > pcbp->yMax)

     {

         // 使y坐标指向第一行

          pcbp->yText = pcbp->yStart ;

          // x坐标增加一行字符串最大宽度,并与可输出最大列比较

          // 如果输出已到最大行和最大列,则返回FALSE

          if ((pcbp->xText += pcbp->xIncr) > pcbp->xMax)

               return FALSE ;

     }

     return TRUE ;

}

3、dll中的字符串获取并显示函数(在内部调用了字符串显示函数)

EXPORT int CALLBACK GetStringsW (GETSTRCB pfnGetStrCallBack, PVOID pParam)

{

     BOOL bReturn ;

     int  i ;

     for (i = 0 ; i < iTotal ; i++)

     {    //在这里回调了应用程序实例中的字符串显示函数,因为显示只能在各个实例中显示,dll是不能帮助显示的,dll并不知道实例中的显示参数或者显示的上下文环境,因而不能在此直接写出显示的代码,而是要待用实例中的函数,让实例自己去做显示的工作,因为只有它自己才知道如何根据显示的DC来显示。其实这个函数主要的工作就是获取共享数据,因为数据是在dll的控制范围之内的。

          bReturn = pfnGetStrCallBack (szStrings[i], pParam) ;

          if (bReturn == FALSE)

               return i + 1 ;

     }

     return iTotal ;

}

4、全局消息注册

    // 注册字符串更改消息,这个消息是各个实例都能收到的,可参考MSDN

  iDataChangeMsg = RegisterWindowMessage (TEXT ("StrProgDataChange")) ;

5、向其他实例广播消息(当在对话框中做出操作之后,会引起共享数据变化,因此向其他实例广播消息,让它们刷新显示)

 // 创建输入对话框(删除对话框行为类似,不再分析)

 if (DialogBox (hInst, TEXT ("EnterDlg"), hwnd, &DlgProc)

{

    // 添加用户输入的字符串到共享内存的字符串数组中

   if (AddString (szString))

   // 将程序注册的消息发送给所有窗口,用于通知使用共享内存的其它程序

     PostMessage (HWND_BROADCAST, iDataChangeMsg, 0, 0) ;

   else

        MessageBeep (0) ;

 }

 6、窗口收到广播消息(收到广播消息,立马让客户区无效,从而引起刷新)

default:

         // 广播消息,刷新客户区

          if (message == iDataChangeMsg)

               InvalidateRect (hwnd, NULL, TRUE) ;

7、更新显示(对应共享数据的修改,每个实例做出更新显示)

case WM_PAINT:

          hdc = BeginPaint (hwnd, &ps) ;

          // 初始化输出字符串所需要的数据

          cbparam.hdc   = hdc ;

          cbparam.xText = cbparam.xStart = cxChar ;

          cbparam.yText = cbparam.yStart = cyChar ;

          cbparam.xIncr = cxChar * MAX_LENGTH ;

          cbparam.yIncr = cyChar ;

          cbparam.xMax  = cbparam.xIncr * (1 + cxClient / cbparam.xIncr) ;

          cbparam.yMax  = cyChar * (cyClient / cyChar - 1) ;     

          // 输出字符串

          GetStrings ((GETSTRCB) GetStrCallBack, (PVOID) &cbparam) ;

          EndPaint (hwnd, &ps) ;

          return 0 ;

 

ps:其他的注意事项还有一些工程配置问题,以及应用程序对dll的依赖配置。

posted @ 2011-04-19 17:46  harryshayne  阅读(531)  评论(0编辑  收藏  举报