windows 程序设计「StrProg」 范例分析笔记

/*--------------------------------------------------------

   STRPROG.C -- Program using STRLIB dynamic-link library

                (c) Charles Petzold, 1998

  --------------------------------------------------------*/

 

#include <windows.h>

#include "strlib.h"

#include "resource.h"

 

typedef struct

{

     HDC hdc ;

     int xText ;

     int yText ;

     int xStart ;

     int yStart ;

     int xIncr ;

     int yIncr ;

     int xMax ;

     int yMax ;

}

CBPARAM ;

 

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

 

TCHAR szAppName [] = TEXT ("StrProg") ;

TCHAR szString [MAX_LENGTH + 1] ;

 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    PSTR szCmdLine, int iCmdShow)

{

     HWND     hwnd ;

     MSG      msg ;

     WNDCLASS wndclass ;

    

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;

     wndclass.lpfnWndProc   = WndProc ;

     wndclass.cbClsExtra    = 0 ;

     wndclass.cbWndExtra    = 0 ;

     wndclass.hInstance     = hInstance ;

     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;

     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

     wndclass.lpszMenuName  = szAppName ;

     wndclass.lpszClassName = szAppName ;

    

     if (!RegisterClass (&wndclass))

     {

          MessageBox (NULL, TEXT ("This program requires Windows NT!"),

                      szAppName, MB_ICONERROR) ;

          return 0 ;

     }

 

     hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),

                          WS_OVERLAPPEDWINDOW,

                          CW_USEDEFAULT, CW_USEDEFAULT,

                          CW_USEDEFAULT, CW_USEDEFAULT,

                          NULL, NULL, hInstance, NULL) ;

    

     ShowWindow (hwnd, iCmdShow) ;

     UpdateWindow (hwnd) ;

    

     while (GetMessage (&msg, NULL, 0, 0))

     {

          TranslateMessage (&msg) ;

          DispatchMessage (&msg) ;

     }

     return msg.wParam ;

}

 

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

     switch (message)

     {

     case WM_INITDIALOG:

         // 向对话框中的文本输入控件发送EM_LIMITTEXT消息,规定用户最大输入字符数为MAX_LENGTH常量

          SendDlgItemMessage (hDlg, IDC_STRING, EM_LIMITTEXT, MAX_LENGTH, 0) ;

          return TRUE ;

         

     case WM_COMMAND:

          switch (wParam)

          {

          case IDOK:

              // 读取文本输入控件中的字符串到szString全局缓冲区中

               GetDlgItemText (hDlg, IDC_STRING, szString, MAX_LENGTH) ;

               EndDialog (hDlg, TRUE) ;

               return TRUE ;

              

          case IDCANCEL:

               EndDialog (hDlg, FALSE) ;

               return TRUE ;

          }

     }

     return FALSE ;

}

 

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 ;

}

 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     static HINSTANCE  hInst ;

     static int        cxChar, cyChar, cxClient, cyClient ;

     static UINT       iDataChangeMsg ;

     CBPARAM           cbparam ;

     HDC               hdc ;

     PAINTSTRUCT       ps ;

     TEXTMETRIC        tm ;

    

     switch (message)

     {

     case WM_CREATE:

          hInst = ((LPCREATESTRUCT) lParam)->hInstance ;

          hdc   = GetDC (hwnd) ;

          GetTextMetrics (hdc, &tm) ;

          cxChar = (int) tm.tmAveCharWidth ;

          cyChar = (int) (tm.tmHeight + tm.tmExternalLeading) ;

          ReleaseDC (hwnd, hdc) ;

 

               // 注册字符串更改消息

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

          return 0 ;

         

     case WM_COMMAND:

          switch (wParam)

          {

          case IDM_ENTER:

              // 创建输入对话框

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

               {

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

                    if (AddString (szString))

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

                         PostMessage (HWND_BROADCAST, iDataChangeMsg, 0, 0) ;

                    else

                         MessageBeep (0) ;

               }

               break ;

              

          case IDM_DELETE:

              // 创建删除对话框

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

               {

                    if (DeleteString (szString))

                         PostMessage (HWND_BROADCAST, iDataChangeMsg, 0, 0) ;

                    else

                         MessageBeep (0) ;

               }

               break ;

          }

          return 0 ;

         

     case WM_SIZE:

          cxClient = (int) LOWORD (lParam) ;

          cyClient = (int) HIWORD (lParam) ;

          return 0 ;

              

     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 ;

              

     case WM_DESTROY:

          PostQuitMessage (0) ;

          return 0 ;

 

     default:

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

          if (message == iDataChangeMsg)

               InvalidateRect (hwnd, NULL, TRUE) ;

          break ;

     }

     return DefWindowProc (hwnd, message, wParam, lParam) ;

}

 

 


 

 

/*------------------------------------------------

   STRLIB.C -- Library module for STRPROG program

               (c) Charles Petzold, 1998

  ------------------------------------------------*/

 

#include <windows.h>

#include <wchar.h>       // for wide-character string functions

#include "strlib.h"

 

// 创建名为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")

 

int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)

{

     return TRUE ;

}

 

EXPORT BOOL CALLBACK AddStringA (PCSTR pStringIn)

{

     BOOL  bReturn ;

     int   iLength ;

     PWSTR pWideStr ;

 

     /* MultiByteToWideChar 映射一个字符串到一个宽字符(unicode)的字符串

        CP_ACPANSI代码页;

        参数二: 一组位标记用以指出是否未转换成预作或宽字符(若组合形式存在)

                是否使用象形文字替代控制字符,以及如何处理无效字符

                缺省动作是转换成预作的形式;

        pStringIn 指向将被转换字符串的字符;

        -1 字符串将被设定为以NULL为结束符的字符串,并且自动计算长度;

        NULL 为指定用于接收的缓冲区;

        0    函数返回缓冲区所必需的宽字符数 */

     iLength = MultiByteToWideChar (CP_ACP, 0, pStringIn, -1, NULL, 0) ;

     // 分配内存,实际转换

     pWideStr = malloc (iLength) ;

     MultiByteToWideChar (CP_ACP, 0, pStringIn, -1, pWideStr, iLength) ;

     // 调用自定义宽字符处理函数做实际处理

     bReturn = AddStringW (pWideStr) ;

     free (pWideStr) ;

 

     return bReturn ;

}

 

EXPORT BOOL CALLBACK AddStringW (PCWSTR pStringIn)

{

     PWSTR pString ;

     int   i, iLength ;

 

     // 依字符串总数做有效性检查

     if (iTotal == MAX_STRINGS - 1)

          return FALSE ;

 

     // 返回宽字符串长度,并做有效性检查

     if ((iLength = wcslen (pStringIn)) == 0)

          return FALSE ;

 

     // 分配字符串内存

     pString = malloc (sizeof (WCHAR) * (1 + iLength)) ;

     // 复制字符串

     wcscpy (pString, pStringIn) ;

     // 将复制的字符串转换为大写

     _wcsupr (pString) ;

 

          // Alphabetize the strings

    

     for (i = iTotal ; i > 0 ; i--)

     {

         // 如果pString 大于或等于 szStrings[i - 1] ,则退出排序

          if (wcscmp (pString, szStrings[i - 1]) >= 0)

               break ;

         // 字符串数组预留位置

          wcscpy (szStrings[i], szStrings[i - 1]) ;

     }

     // 复制新字符串到字符串数组

     wcscpy (szStrings[i], pString) ;

     // 字符串计数加一

     iTotal++ ;

 

     free (pString) ;

     return TRUE ;

}

 

EXPORT BOOL CALLBACK DeleteStringA (PCSTR pStringIn)

{

     BOOL  bReturn ;

     int   iLength ;

     PWSTR pWideStr ;

 

     // 和添加函数一样,转换字符串为宽字符串,并使用宽字符串处理函数来实作

     iLength = MultiByteToWideChar (CP_ACP, 0, pStringIn, -1, NULL, 0) ;

     pWideStr = malloc (iLength) ;

     MultiByteToWideChar (CP_ACP, 0, pStringIn, -1, pWideStr, iLength) ;

     bReturn = DeleteStringW (pWideStr) ;

     free (pWideStr) ;

 

     return bReturn ;

}

 

EXPORT BOOL CALLBACK DeleteStringW (PCWSTR pStringIn)

{

     int i, j ;

    

     // 判断是否输入字符串

     if (0 == wcslen (pStringIn))

          return FALSE ;

    

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

     {

         // 如果 szStrings[i] 等于 pStringIn _wcsicmp的返回值为0

          if (_wcsicmp (szStrings[i], pStringIn) == 0)

               break ;

     }

 

     // 如果因为循环判断公式错误而退出循环,表明给定的字符串不在列表中

     if (i == iTotal)

          return FALSE ;

 

     // 否者从找到的字符串开始,向下重排

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

          wcscpy (szStrings[j], szStrings[j + 1]) ;

    

     // 删除之前的字符串数组尾,调整字符串计数

     szStrings[iTotal--][0] = '/0' ;

     return TRUE ;

}

 

EXPORT int CALLBACK GetStringsA (GETSTRCB pfnGetStrCallBack, PVOID pParam)

{

     BOOL bReturn ;

     int  i, iLength ;

     PSTR pAnsiStr ;

 

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

     {

         // 转换成宽字符串

          iLength = WideCharToMultiByte (CP_ACP, 0, szStrings[i], -1, NULL, 0,

                                         NULL, NULL) ;

          pAnsiStr = malloc (iLength) ;

          WideCharToMultiByte (CP_ACP, 0, szStrings[i], -1, pAnsiStr, iLength,

                                          NULL, NULL) ;

          // 调用主程序的回调函数

          bReturn = pfnGetStrCallBack (pAnsiStr, pParam) ;

         

          // 如果输出超出屏幕大小,则退出函数

          if (bReturn == FALSE)

               return i + 1 ;

 

          free (pAnsiStr) ;

     }

     return iTotal ;

}

 

EXPORT int CALLBACK GetStringsW (GETSTRCB pfnGetStrCallBack, PVOID pParam)

{

     BOOL bReturn ;

     int  i ;

    

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

     {

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

         

          if (bReturn == FALSE)

               return i + 1 ;

     }

     return iTotal ;

}

 

 

 


 

/*----------------------

   STRLIB.H header file

  ----------------------*/

 

 

// 如果程序是CPP程序

#ifdef __cplusplus

// 告诉编译器用C的方式来链接

#define EXPORT extern "C" __declspec (dllexport)

#else

/* __declspec(dllexport)   声明一个导出函数,一般用于dll中
   __declspec(dllimport)   声明一个导入函数,一般用于使用某个dll的exe中 */

#define EXPORT __declspec (dllexport)

#endif

 

     // The maximum number of strings STRLIB will store and their lengths

 

#define MAX_STRINGS 256

#define MAX_LENGTH  64

 

     // The callback function type definition uses generic strings

 

typedef BOOL (CALLBACK * GETSTRCB) (PCTSTR, PVOID) ;

 

     // Each function has ANSI and Unicode versions

 

EXPORT BOOL CALLBACK AddStringA (PCSTR) ;

EXPORT BOOL CALLBACK AddStringW (PCWSTR) ;

 

EXPORT BOOL CALLBACK DeleteStringA (PCSTR) ;

EXPORT BOOL CALLBACK DeleteStringW (PCWSTR) ;

 

EXPORT int CALLBACK GetStringsA (GETSTRCB, PVOID) ;

EXPORT int CALLBACK GetStringsW (GETSTRCB, PVOID) ;

 

     // Use the correct version depending on the UNICODE identifier

 

#ifdef UNICODE

#define AddString    AddStringW

#define DeleteString DeleteStringW

#define GetStrings   GetStringsW

#else

#define AddString    AddStringA

#define DeleteString DeleteStringA

#define GetStrings   GetStringsA

#endif

 


 

//资源文件

//

#include "resource.h"

 

#define APSTUDIO_READONLY_SYMBOLS

/

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

 

/

#undef APSTUDIO_READONLY_SYMBOLS

 

/

// English (U.S.) resources

 

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

#ifdef _WIN32

LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

#pragma code_page(1252)

#endif //_WIN32

 

#ifdef APSTUDIO_INVOKED

/

//

// TEXTINCLUDE

//

 

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h/0"

END

 

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""/r/n"

    "/0"

END

 

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "/r/n"

    "/0"

END

 

#endif    // APSTUDIO_INVOKED

 

 

/

//

// Dialog

//

 

ENTERDLG DIALOG DISCARDABLE  20, 20, 186, 47

STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU

CAPTION "Enter"

FONT 8, "MS Sans Serif"

BEGIN

    LTEXT           "&Enter:",IDC_STATIC,7,7,26,9

    EDITTEXT        IDC_STRING,31,7,148,12,ES_AUTOHSCROLL

    DEFPUSHBUTTON   "OK",IDOK,32,26,50,14

    PUSHBUTTON      "Cancel",IDCANCEL,104,26,50,14

END

 

DELETEDLG DIALOG DISCARDABLE  20, 20, 186, 47

STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU

CAPTION "Delete"

FONT 8, "MS Sans Serif"

BEGIN

    LTEXT           "&Delete:",IDC_STATIC,7,7,26,9

    EDITTEXT        IDC_STRING,31,7,148,12,ES_AUTOHSCROLL

    DEFPUSHBUTTON   "OK",IDOK,32,26,50,14

    PUSHBUTTON      "Cancel",IDCANCEL,104,26,50,14

END

 

 

/

//

// Menu

//

 

STRPROG MENU DISCARDABLE

BEGIN

    MENUITEM "&Enter!",                     IDM_ENTER

    MENUITEM "&Delete!",                    IDM_DELETE

END

 

 

/

//

// DESIGNINFO

//

 

#ifdef APSTUDIO_INVOKED

GUIDELINES DESIGNINFO DISCARDABLE

BEGIN

    "ENTERDLG", DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 179

        TOPMARGIN, 7

        BOTTOMMARGIN, 40

    END

 

    "DELETEDLG", DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 179

        TOPMARGIN, 7

        BOTTOMMARGIN, 40

    END

END

#endif    // APSTUDIO_INVOKED

 

#endif    // English (U.S.) resources

/

 

 

 

#ifndef APSTUDIO_INVOKED

/

//

// Generated from the TEXTINCLUDE 3 resource.

//

 

 

/

#endif    // not APSTUDIO_INVOKED

 


 

VS2010 项目配置

 

修改项目的依赖关系

 

在项目名称上点击右键,选择项目依赖项。如图:

 

依赖项

 

 

设置项目的DLL文件依赖

 

在主程序的项目名称上点击右键,选择属性。在新窗口中点击 配置属性->链接器->输入,右边的 附加依赖项 中写入需要引入的DLL文件的链接文件(*.lib)。如图:

 

DLL依赖项

 

设置共享内存节的特性

 

选择 DLL 项目的属性,配置属性->链接器->常规->指定节特性。如图:

 

节特性

 

 

字母 RWS 表示数据段具有读、写和共享属性。

也可以直接用DLL原始码指定连结选项

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值