bucket.dpr

来自「一本已经绝版的好书」· DPR 代码 · 共 336 行

DPR
336
字号

// Module name: Bucket.C ->> Bucket.dpr
// Notices: Copyright (c) 1995-1997 Jeffrey Richter
// Translator: 刘麻子, Liu_mazi@126.com

program Bucket;

{$R 'Bucket.res' 'Bucket.rc'}

uses
  Windows, Messages, SWMRG in 'SWMRG.pas',
  Other in '..\Other.pas', CmnHdr in '..\CmnHdr.pas', WindowsX in '..\WindowsX.pas';

const
  IDD_BUCKET     =      1;
  IDC_WRITE1NUM  =    100;
  IDC_WRITE1SCRL =    101;
  IDC_WRITE2NUM  =    102;
  IDI_BUCKET     =    102;
  IDC_WRITE2SCRL =    103;
  IDC_READ1NUM   =    104;
  IDC_READ1SCRL  =    105;
  IDC_READ1LIST  =    106;
  IDC_READ2NUM   =    107;
  IDC_READ2SCRL  =    108;
  IDC_READ2LIST  =    109;
  IDC_READ3NUM   =    110;
  IDC_READ3SCRL  =    111;
  IDC_READ3LIST  =    112;

var
  g_SWMRG: TSWMRG;                    // 同步对象
  g_hThreads: array[0..4] of THandle; // 线程对象
  g_lTerminate: Integer = 0;          // 退出标志
  g_hWndDlg: HWND;                    // 界面窗口

type
  TBallColor =
    (
    BC_NULL, BC_BLACK, BC_RED, BC_GREEN, BC_BLUE, BC_WHITE, BC_YELLOW, BC_ORANGE, BC_CYAN, BC_GRAY,
    BC_FIRSTBALLCLR = BC_NULL, BC_LASTBALLCLR  = BC_GRAY
    );

const
  szBallColors: array[TBallColor] of PChar =
    ( nil, 'Black', 'Red', 'Green', 'Blue', 'White', 'Yellow', 'Orange', 'Cyan', 'Gray' );
  MAX_BALLS = 100;

var
  g_Bucket: array[0..MAX_BALLS - 1] of TBallColor; // = { BC_NULL }

  // 随机存取
procedure Bucket_AlterContents();
begin
  g_Bucket[Random(MAX_BALLS)] := TBallColor(Random(10));
end;

  // 数量统计
procedure Bucket_DumpToLB(hWndLB: HWND);
var
  BallColor: TBallColor;
  nBallNum, nBlank: Integer;
  nBallColor: array[TBallColor] of Integer; // = { 0 }
  szBuf, szBlank: array[0..50] of Char;
begin
  // 分类统计
  ZeroMemory(@nBallColor, SizeOf(nBallColor));
  for nBallNum := 0 to MAX_BALLS - 1 do
  begin
    BallColor := g_Bucket[nBallNum]; // nBallNum号球的颜色
    Inc(nBallColor[BallColor]);      // 对应颜色计数值增加
  end;

  // 刷新列表
  ListBox_ResetContent(hWndLB);
  for BallColor := BC_FIRSTBALLCLR to BC_LASTBALLCLR do
  begin
    if (szBallColors[BallColor] <> nil) then
    begin
      nBlank := 7 - lstrlen(szBallColors[BallColor]);
      szBlank[nBlank] := #0;
      FillMemory(@szBlank, nBlank, $20);

      _wvsprintf(szBuf, '%s: %s%2d', [ DWORD(szBallColors[BallColor]), DWORD(@szBlank), nBallColor[BallColor] ]);
    end else
      _wvsprintf(szBuf, 'Total:   %2d', [ MAX_BALLS - nBallColor[BallColor] ]);

    ListBox_AddString(hWndLB, szBuf);
  end;
end;

  // 写入线程
function Writer(nWriterNum: Integer): Integer; // **
var
  nNumID: DWORD;
begin
  case (nWriterNum) of
    1: nNumID := IDC_WRITE1NUM;
    2: nNumID := IDC_WRITE2NUM;
    else nNumID := 0;
  end;

  while (g_lTerminate = 0) do
  begin
    // 挂起指定时间
    Sleep(1000 * GetDlgItemInt(g_hWndDlg, nNumID, PBOOL(nil)^, FALSE));

    // 等待写入权限
    SWMRGWaitToWrite(g_SWMRG, INFINITE);

    // 修改共享数据
    Bucket_AlterContents();

    // 释放写入权限
    SWMRGDoneWriting(g_SWMRG);
  end;

  Result := 0;
end;

  // 读取线程
function Reader(nReaderNum: Integer): Integer;
var
  nNumID: DWORD;
  hWndLB: HWND;
begin
  case (nReaderNum) of
    1: begin
         nNumID := IDC_READ1NUM;
         hWndLB := GetDlgItem(g_hWndDlg, IDC_READ1LIST);
       end;

    2: begin
         nNumID := IDC_READ2NUM;
         hWndLB := GetDlgItem(g_hWndDlg, IDC_READ2LIST);
       end;

    3: begin
         nNumID := IDC_READ3NUM;
         hWndLB := GetDlgItem(g_hWndDlg, IDC_READ3LIST);
       end;

    else begin
         nNumID := 0;
         hWndLB := 0;
       end;
  end;

  while (g_lTerminate = 0) do
  begin
    // 挂起指定时间
    Sleep(1000 * GetDlgItemInt(g_hWndDlg, nNumID, PBOOL(nil)^, FALSE));

    // 等待读取权限
    SWMRGWaitToRead(g_SWMRG, INFINITE);

    // 读出共享数据
    Bucket_DumpToLB(hWndLB);

    // 释放读取权限
    SWMRGDoneReading(g_SWMRG);
  end;

  Result := 0;
end;

  // WM_INITDIALOG
function Dlg_OnInitDialog(hWnd, hWndFocus: HWND; lParam: LPARAM): BOOL;
var
  dwThreadID: DWORD;
  x: Integer;
begin
  chSETDLGICONS(hWnd, IDI_BUCKET, IDI_BUCKET);
  g_hWndDlg := hWnd;

  ScrollBar_SetRange(GetDlgItem(hWnd, IDC_WRITE1SCRL), 0, 60, FALSE);
  ScrollBar_SetPos(GetDlgItem(hWnd, IDC_WRITE1SCRL), 1, TRUE);
  SetDlgItemInt(hWnd, IDC_WRITE1NUM, 1, FALSE);

  ScrollBar_SetRange(GetDlgItem(hWnd, IDC_WRITE2SCRL), 0, 60, FALSE);
  ScrollBar_SetPos(GetDlgItem(hWnd, IDC_WRITE2SCRL), 3, TRUE);
  SetDlgItemInt(hWnd, IDC_WRITE2NUM, 3, FALSE);

  ScrollBar_SetRange(GetDlgItem(hWnd, IDC_READ1SCRL), 0, 60, FALSE);
  ScrollBar_SetPos(GetDlgItem(hWnd, IDC_READ1SCRL), 2, TRUE);
  SetDlgItemInt(hWnd, IDC_READ1NUM, 2, FALSE);

  ScrollBar_SetRange(GetDlgItem(hWnd, IDC_READ2SCRL), 0, 60, FALSE);
  ScrollBar_SetPos(GetDlgItem(hWnd, IDC_READ2SCRL), 4, TRUE);
  SetDlgItemInt(hWnd, IDC_READ2NUM, 4, FALSE);
  
  ScrollBar_SetRange(GetDlgItem(hWnd, IDC_READ3SCRL), 0, 60, FALSE);
  ScrollBar_SetPos(GetDlgItem(hWnd, IDC_READ3SCRL), 7, TRUE);
  SetDlgItemInt(hWnd, IDC_READ3NUM, 7, FALSE);

  for x := 0 to 1 do
  begin
    g_hThreads[x] := BeginThread(nil, 0, @Writer, Pointer(x + 1), 0, dwThreadID);
  end;

  for x := 2 to 4 do
  begin
    g_hThreads[x] := BeginThread(nil, 0, @Reader, Pointer(x - 1), 0, dwThreadID);
  end;

  Result := TRUE;
end;

  // WM_HSCROLL
procedure Dlg_OnHScroll(hWnd, hWndCtl: HWND; code: UINT; pos: Integer);
var
  posCrnt, posMin, posMax: Integer;
begin
  posCrnt := ScrollBar_GetPos(hWndCtl);
  ScrollBar_GetRange(hWndCtl, @posMin, @posMax);

  case (code) of
    SB_LINELEFT:
      Dec(posCrnt);

    SB_LINERIGHT:
      Inc(posCrnt);

    SB_PAGELEFT:
      Dec(posCrnt, 10);

    SB_PAGERIGHT:
      Inc(posCrnt, 10);

    SB_THUMBTRACK:
      posCrnt := pos;

    SB_LEFT:
      posCrnt := 0;

    SB_RIGHT:
      posCrnt := posMax;
  end;

  if (posCrnt < 0) then posCrnt := 0 else if (posCrnt > posMax) then posCrnt := posMax;

  ScrollBar_SetPos(hWndCtl, posCrnt, TRUE);
  SetDlgItemInt(hWnd, GetDlgCtrlID(hWndCtl) - 1, posCrnt, FALSE);
end;

  // WM_VSCROLL
procedure Dlg_OnVScroll(hWnd, hWndCtl: HWND; code: UINT; pos: Integer);
var
  posCrnt, posMin, posMax: Integer;
begin
  posCrnt := ScrollBar_GetPos(hWndCtl);
  ScrollBar_GetRange(hWndCtl, @posMin, @posMax);

  case (code) of
    SB_LINEUP:
      Dec(posCrnt);

    SB_LINEDOWN:
      Inc(posCrnt);

    SB_PAGEUP:
      Dec(posCrnt, 10);

    SB_PAGEDOWN:
      Inc(posCrnt, 10);

    SB_THUMBTRACK:
      posCrnt := pos;

    SB_TOP:
      posCrnt := 0;

    SB_BOTTOM:
      posCrnt := posMax;
  end;

  if (posCrnt < 0) then posCrnt := 0 else if (posCrnt > posMax) then posCrnt := posMax;

  ScrollBar_SetPos(hWndCtl, posCrnt, TRUE);
  SetDlgItemInt(hWnd, GetDlgCtrlID(hWndCtl) - 1, posCrnt, FALSE);
end;

  // WM_COMMAND
procedure Dlg_OnCommand(hWnd: HWND; id: Integer; hWndCtl: HWND; codeNotify: UINT);
begin
  if (id = IDCANCEL) then EndDialog(hWnd, id);
end;

  // 对话框回调
function Dlg_Proc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;
begin
  case (uMsg) of
    WM_INITDIALOG:
      begin
        Result := SetDlgMsgResult(hWnd, LRESULT(Dlg_OnInitDialog(hWnd, wParam, lParam)));
      end;
      
    WM_COMMAND:
      begin
        Dlg_OnCommand(hWnd, LOWORD(wParam), lParam, HIWORD(wParam));
        Result := TRUE;
      end;

    WM_HSCROLL:
      begin
        Dlg_OnHScroll(hWnd, lParam, LOWORD(wParam), HIWORD(wParam));
        Result := TRUE;
      end;

    WM_VSCROLL:
      begin
        Dlg_OnVScroll(hWnd, lParam, LOWORD(wParam), HIWORD(wParam));
        Result := TRUE;
      end;

    else Result := FALSE;
  end;
end;

  // 主线程入口
var
  x: Integer;
begin
  chWARNIFUNICODEUNDERWIN95();

  SWMRGInitialize(g_SWMRG, nil);

  DialogBox(HInstance, MakeIntResource(IDD_BUCKET), 0, @Dlg_Proc);

  InterlockedIncrement(g_lTerminate);
  WaitForMultipleObjects(chDIMOF(g_hThreads), @g_hThreads, TRUE, INFINITE);
  for x := 0 to chDIMOF(g_hThreads) - 1 do CloseHandle(g_hThreads[x]);
  
  SWMRGDelete(g_SWMRG);
end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?