sprmrkt.dpr
来自「一本已经绝版的好书」· DPR 代码 · 共 382 行
DPR
382 行
// Module name: SprMrkt.C ->> SprMrkt.dpr
// Notices: Copyright (c) 1995-1997 Jeffrey Richter
// Translator: 刘麻子, Liu_mazi@126.com
program SprMrkt;
{$R 'SprMrkt.res' 'SprMrkt.rc'}
uses
Windows, Messages,
Other in '..\Other.pas', CmnHdr in '..\CmnHdr.pas', WindowsX in '..\WindowsX.pas';
const
IDD_SPRMRKT = 1;
IDC_MAXOCCUPANCY = 100;
IDC_TIMEOPEN = 101;
IDI_SPRMRKT = 101;
IDC_NUMCOUNTERS = 102;
IDC_SHOPPERCREATIONDELAY = 103;
IDC_DELAYTOGETIN = 104;
IDC_TIMETOSHOP = 105;
IDC_WAITDELICNTR = 106;
IDC_TIMEATDELICNTR = 107;
IDC_TIMEATCHECKOUT = 108;
IDC_SHOPPEREVENTS = 109;
var
g_hWndLB: HWND = 0; // 信息输出ListBox句柄
var
g_nMaxOccupancy, // 超市最多可容纳人数
g_nTimeOpen, // 超市本次开放时长
g_nCheckoutCounters, // 超市结帐柜台数量
g_nMaxDelayBetweenShopperCreation, // 产生新顾客的最大时间间隔
g_nMaxWaitToGetInMarket, // 顾客等待进入超市, 最长等待时间
g_nMaxTimeShopping, // 顾客购物, 最多耗费时间
g_nMaxWaitForDeliCntr, // 顾客等待购买熟食, 最长等待时间
g_nMaxTimeSpentAtDeli, // 顾客购买熟食, 最多耗费时间
g_nMaxTimeAtCheckout: Integer; // 顾客结帐, 最多耗费时间
var
g_hSemEntrance, // 控制进入超市人数
g_hMtxDeliCntr, // 控制一一购买熟食
g_hSemCheckout: THandle; // 控制柜台结帐人数
// 向ListBox添加格式化字符串
procedure AddStr(const szFmt: PChar; const va_params: array of DWORD);
var
szBuf: array[0..150] of Char;
nIndex: Integer;
begin
Windows.wvsprintf(szBuf, szFmt, @va_params);
repeat
nIndex := ListBox_AddString(g_hWndLB, szBuf);
if (nIndex = LB_ERR) then ListBox_DeleteString(g_hWndLB, 0) else Break;
until FALSE;
ListBox_SetCurSel(g_hWndLB, nIndex);
end;
// 0 <= Result <= nMaxValue
function Random(nMaxValue: Integer): Integer;
begin
Result := System.Random(nMaxValue + 1);
end;
// 顾客线程回调函数
function ThreadShopper(nShopperNum: Integer): Integer;
var
dwResult: DWORD;
nDuration: Integer;
begin
Result := 0;
Randomize();
// 进入等待时长
nDuration := Random(g_nMaxWaitToGetInMarket);
AddStr('%04lu: Waiting to get in store (%lu).', [nShopperNum, nDuration]);
// 等待进入超市
dwResult := WaitForSingleObject(g_hSemEntrance, nDuration);
if (dwResult = WAIT_TIMEOUT) then
begin
AddStr('%04lu: Tired of waiting; went home.', [nShopperNum]); // 超时回家 ^^
Exit;
end;
// 购物一段时间
nDuration := Random(g_nMaxTimeShopping);
AddStr('%04lu: In supermarket, shopping for %lu.', [nShopperNum, nDuration]);
Sleep(nDuration);
// 可能购买熟食
if (Random(2) = 0) then
begin
// 购买等待时长
nDuration := Random(g_nMaxWaitForDeliCntr);
AddStr('%04lu: Waiting for service at Deli Counter (%lu).', [nShopperNum, nDuration]);
// 等待购买熟食
dwResult := WaitForSingleObject(g_hMtxDeliCntr, nDuration);
if (dwResult = STATUS_WAIT_0) then
begin
// 购买熟食耗时
nDuration := Random(g_nMaxTimeSpentAtDeli);
AddStr('%04lu: Being served at Deli (%lu).', [nShopperNum, nDuration]);
Sleep(nDuration);
// 购买熟食完成
ReleaseMutex(g_hMtxDeliCntr);
end else
begin
AddStr('%04lu: Tired of waiting at Deli.', [nShopperNum]); // 超时离开 ^^
end;
end else
begin
AddStr('%04lu: Not going to the Deli counter.', [nShopperNum]); // 不买熟食 ^^
end;
// 等待柜台结帐
AddStr('%04lu: Waiting for an empty checkout counter.', [nShopperNum]);
WaitForSingleObject(g_hSemCheckout, INFINITE);
// 结帐消耗时间
nDuration := Random(g_nMaxTimeAtCheckout);
AddStr('%04lu: Checking out (%lu).', [nShopperNum, nDuration]);
Sleep(nDuration);
// 完成柜台结帐
AddStr('%04lu: Leaving checkout counter.', [nShopperNum]);
ReleaseSemaphore(g_hSemCheckout, 1, nil);
// 离开超市回家
AddStr('%04lu: Left the supermarket.', [nShopperNum]);
ReleaseSemaphore(g_hSemEntrance, 1, nil);
end;
// 超市线程回调函数
function ThreadSuperMarket(hWnd: HWND): Integer;
var
dwCloseTime: DWORD;
hThread: THandle;
dwThreadId: DWORD;
nShopperNum: Integer; // = 0
nMaxOccupancy: Integer;
begin
nShopperNum := 0; // 顾客数量?
// 顾客进入限制
g_hSemEntrance := CreateSemaphore(nil, 0, g_nMaxOccupancy, nil);
// 熟食购买限制
g_hMtxDeliCntr := CreateMutex(nil, FALSE, nil);
// 结帐柜台限制
g_hSemCheckout := CreateSemaphore(nil, g_nCheckoutCounters, g_nCheckoutCounters, nil);
// 打开超市大门
AddStr('---> Opening the supermarket to shoppers.', []);
ReleaseSemaphore(g_hSemEntrance, g_nMaxOccupancy, nil);
// 超市关门时间
dwCloseTime := GetTickCount() + DWORD(g_nTimeOpen);
// 超市开始运转
while (GetTickCount() < dwCloseTime) do
begin
// 产生一位顾客
hThread := BeginThread(nil, 0, @ThreadShopper, Pointer(nShopperNum), 0, dwThreadId);
CloseHandle(hThread);
Inc(nShopperNum);
// 下位来临间隔
Sleep(Random(g_nMaxDelayBetweenShopperCreation));
end;
// 超市准备关门
AddStr('---> Waiting for shoppers to check out ', [DWORD(PChar('so store can close.'))]);
// 等待顾客离开
for nMaxOccupancy := 1 to g_nMaxOccupancy - 1 do
begin
WaitForSingleObject(g_hSemEntrance, INFINITE);
AddStr('---> %d shoppers NOT in store.', [nMaxOccupancy]);
end;
// 关闭超市大门
AddStr('---> Store closed--end of simulation.', []);
// 清除内核对象
CloseHandle(g_hSemCheckout);
CloseHandle(g_hMtxDeliCntr);
CloseHandle(g_hSemEntrance);
// 通知界面更新
SendMessage(hWnd, WM_USER, 0, 0);
Result := 0;
end;
// WM_INITDIALOG
function Dlg_OnInitDialog(hWnd, hWndFocus: HWND; lParam: LPARAM): BOOL;
var
hWndSB: DWORD; // HWND
begin
chSETDLGICONS(hWnd, IDI_SPRMRKT, IDI_SPRMRKT);
g_hWndLB := GetDlgItem(hWnd, IDC_SHOPPEREVENTS);
hWndSB := GetDlgItem(hWnd, IDC_MAXOCCUPANCY);
ScrollBar_SetRange(hWndSB, 0, 500, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 30);
hWndSB := GetDlgItem(hWnd, IDC_TIMEOPEN);
ScrollBar_SetRange(hWndSB, 0, 5000, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 5000);
hWndSB := GetDlgItem(hWnd, IDC_NUMCOUNTERS);
ScrollBar_SetRange(hWndSB, 0, 30, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 5);
hWndSB := GetDlgItem(hWnd, IDC_SHOPPERCREATIONDELAY);
ScrollBar_SetRange(hWndSB, 0, 1000, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 300);
hWndSB := GetDlgItem(hWnd, IDC_DELAYTOGETIN);
ScrollBar_SetRange(hWndSB, 0, 100, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 20);
hWndSB := GetDlgItem(hWnd, IDC_TIMETOSHOP);
ScrollBar_SetRange(hWndSB, 0, 100, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 80);
hWndSB := GetDlgItem(hWnd, IDC_WAITDELICNTR);
ScrollBar_SetRange(hWndSB, 0, 100, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 20);
hWndSB := GetDlgItem(hWnd, IDC_TIMEATDELICNTR);
ScrollBar_SetRange(hWndSB, 0, 100, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 70);
hWndSB := GetDlgItem(hWnd, IDC_TIMEATCHECKOUT);
ScrollBar_SetRange(hWndSB, 0, 100, TRUE);
FORWARD_WM_HSCROLL(hWnd, hWndSB, SB_THUMBTRACK, 60);
Result := TRUE;
end;
// WM_HSCROLL
procedure Dlg_OnHScroll(hWnd, hWndCtl: HWND; code: UINT; pos: Integer);
var
szBuf: array[0..10] of Char;
nPosCrnt, nPosMin, nPosMax: Integer;
begin
// 范围位置
nPosCrnt := ScrollBar_GetPos(hWndCtl);
ScrollBar_GetRange(hWndCtl, @nPosMin, @nPosMax);
// 动作类型
case (code) of
SB_LINELEFT:
Dec(nPosCrnt);
SB_LINERIGHT:
Inc(nPosCrnt);
SB_PAGELEFT:
Dec(nPosCrnt, (nPosMax - nPosMin + 1) div 10);
SB_PAGERIGHT:
Inc(nPosCrnt, (nPosMax - nPosMin + 1) div 10);
SB_THUMBTRACK:
nPosCrnt := pos;
SB_LEFT:
nPosCrnt := nPosMin;
SB_RIGHT:
nPosCrnt := nPosMax;
end;
// 范围限制
if (nPosCrnt < nPosMin) then
nPosCrnt := nPosMin
else
if (nPosCrnt > nPosMax) then
nPosCrnt := nPosMax;
// 设置位置
ScrollBar_SetPos(hWndCtl, nPosCrnt, TRUE);
// 显示位置
_wvsprintf(szBuf, '%d', [nPosCrnt]);
SetWindowText(GetPrevSibling(hWndCtl), szBuf);
end;
// WM_COMMAND
procedure Dlg_OnCommand(hWnd: HWND; id: Integer; hWndCtl: HWND; codeNotify: UINT);
var
dwThreadId: DWORD;
hThread: THandle;
begin
case (id) of
IDOK:
begin
// 读入参数
g_nMaxOccupancy := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_MAXOCCUPANCY));
g_nTimeOpen := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_TIMEOPEN));
g_nCheckoutCounters := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_NUMCOUNTERS));
g_nMaxDelayBetweenShopperCreation := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_SHOPPERCREATIONDELAY));
g_nMaxWaitToGetInMarket := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_DELAYTOGETIN));
g_nMaxTimeShopping := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_TIMETOSHOP));
g_nMaxWaitForDeliCntr := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_WAITDELICNTR));
g_nMaxTimeSpentAtDeli := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_TIMEATDELICNTR));
g_nMaxTimeAtCheckout := ScrollBar_GetPos(GetDlgItem(hWnd, IDC_TIMEATCHECKOUT));
// 清空列表
ListBox_ResetContent(GetDlgItem(hWnd, IDC_SHOPPEREVENTS));
// 禁用按钮
EnableWindow(hWndCtl, FALSE);
// 设置焦点
if (GetFocus() = 0) then SetFocus(GetDlgItem(hWnd, IDC_MAXOCCUPANCY));
// 高优先级
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
// 超市线程
hThread := BeginThread(nil, 0, @ThreadSuperMarket, Pointer(hWnd), 0, dwThreadId);
CloseHandle(hThread);
end;
IDCANCEL:
begin
EndDialog(hWnd, id);
end;
end;
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_USER: // 超市已关门 ^^
begin
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
EnableWindow(GetDlgItem(hWnd, IDOK), TRUE);
Result := TRUE;
end;
else Result := FALSE;
end;
end;
// 主线程入口
begin
chWARNIFUNICODEUNDERWIN95();
DialogBox(HInstance, MakeIntResource(IDD_SPRMRKT), 0, @Dlg_Proc);
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?