pos機(jī)交互過程,CodeBlock下的人機(jī)交互界面設(shè)計(jì)

 新聞資訊2  |   2023-06-13 10:01  |  投稿人:pos機(jī)之家

網(wǎng)上有很多關(guān)于pos機(jī)交互過程,CodeBlock下的人機(jī)交互界面設(shè)計(jì)的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)交互過程的問題,今天pos機(jī)之家(www.dsth100338.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來看下吧!

本文目錄一覽:

1、pos機(jī)交互過程

pos機(jī)交互過程

人機(jī)交互界面指的是計(jì)算機(jī)系統(tǒng)與用戶之間的接口。通過該接口,一方面,計(jì)算機(jī)系統(tǒng)向用戶輸出系統(tǒng)的運(yùn)行狀態(tài)、運(yùn)行控制和運(yùn)行結(jié)果等方面信息;另一方面,用戶根據(jù)輸出信息向系統(tǒng)輸入相應(yīng)的指令和數(shù)據(jù)等信息。

3.4.1 控制臺(tái)窗口和屏幕緩沖區(qū)

控制臺(tái)窗口是個(gè)二維平面空間,其坐標(biāo)系統(tǒng)的原點(diǎn)(0, 0)設(shè)在窗口左上角,即窗口第一行第一列字符單元的位置。橫軸(X軸)的正向沿原點(diǎn)向右,與窗口的第一行重合,每刻度為一個(gè)字符寬度;縱軸(Y軸)的正向沿原點(diǎn)向下,與窗口的第一列重合,每刻度為一個(gè)字符高度。窗口中每個(gè)字符單元對(duì)應(yīng)一個(gè)二維坐標(biāo)。比如,第5行第32列字符單元的坐標(biāo)為(31, 4)。如圖3.8所示。

圖3.8 控制臺(tái)窗口和屏幕緩沖區(qū)關(guān)系示意圖

屏幕緩沖區(qū)是個(gè)二維數(shù)組,邏輯上可看作一個(gè)二維平面空間。數(shù)組第一個(gè)元素的下標(biāo)[0][0]對(duì)應(yīng)此平面空間坐標(biāo)系統(tǒng)的原點(diǎn)(0, 0),數(shù)組第1維的下標(biāo)對(duì)應(yīng)坐標(biāo)系統(tǒng)的縱坐標(biāo)(Y坐標(biāo)),第2維下標(biāo)對(duì)應(yīng)坐標(biāo)系統(tǒng)的橫坐標(biāo)(X坐標(biāo))。屏幕緩沖區(qū)存放著M行N列字符單元的信息,M和N的大小由系統(tǒng)設(shè)置,并可以進(jìn)行修改。

每個(gè)字符單元信息用一個(gè)Char_INFO結(jié)構(gòu)類型的數(shù)據(jù)來表示,結(jié)構(gòu)成員CHAR存放字符的碼值(Unicode碼或ASCII碼,取決于系統(tǒng)所采用的字符集),結(jié)構(gòu)成員Attributes存放字符的屬性(字符顯示所用的前景色和背景色)。

操作系統(tǒng)以一定的頻率從屏幕緩沖區(qū)讀取字符單元信息,并顯示在控制臺(tái)窗口中。應(yīng)用程序的輸出信息實(shí)際上輸出到了屏幕緩沖區(qū),由此改變了控制臺(tái)窗口所顯示的內(nèi)容。初始狀態(tài)下,屏幕緩沖區(qū)坐標(biāo)系統(tǒng)與控制臺(tái)窗口坐標(biāo)系統(tǒng)重合,窗口中第m行第n列字符的碼值和顏色值存放在屏幕緩沖區(qū)二維數(shù)組中下標(biāo)為[m-1][n-1]的元素中。利用控制臺(tái)函數(shù)可以改變這兩個(gè)坐標(biāo)系統(tǒng)的對(duì)應(yīng)關(guān)系,實(shí)現(xiàn)特殊的顯示效果。圖3.8表示了控制臺(tái)窗口和屏幕緩沖區(qū)的相互關(guān)系。

一個(gè)控制臺(tái)可擁有多個(gè)屏幕緩沖區(qū),但只有處于激活狀態(tài)的屏幕緩沖區(qū)內(nèi)容顯示在控制臺(tái)窗口中。操作系統(tǒng)在為進(jìn)程創(chuàng)建控制臺(tái)的同時(shí)會(huì)創(chuàng)建一個(gè)屏幕緩沖區(qū)。

進(jìn)程可調(diào)用函數(shù)CreateConsoleScreenBuffer為其控制臺(tái)創(chuàng)建另外的屏幕緩沖區(qū)。

調(diào)用函數(shù)SetConsoleActiveScreenBuffer可以將某個(gè)已有的屏幕緩沖區(qū)置為激活狀態(tài),使其內(nèi)容顯示在屏幕窗口中。

不管是否處于激活狀態(tài),屏幕緩沖區(qū)都可以通過句柄來進(jìn)行讀寫操作,只不過激活狀態(tài)下屏幕緩沖區(qū)的內(nèi)容可以看到,非激活狀態(tài)下看不到而已。

屏幕緩沖區(qū)相關(guān)的多個(gè)屬性可以獨(dú)立進(jìn)行設(shè)置。激活的屏幕緩沖區(qū)屬性值的變化能在控制臺(tái)窗口中產(chǎn)生奇妙的外觀效果。屏幕緩沖區(qū)相關(guān)的屬性包括:

l 屏幕緩沖區(qū)大小,以字符行和列為單位;

l 文本屬性(文本信息顯示的前景色和背景色);

l 窗口大小和定位(控制臺(tái)屏幕緩沖區(qū)在控制臺(tái)窗口中顯示時(shí)所處的矩形區(qū)域);

l 光標(biāo)位置、外觀和是否可見;

l 輸出模式(控制字符的輸出處理和行末換行處理)。

屏幕緩沖區(qū)在創(chuàng)建時(shí),它所包含的字符內(nèi)容初始化為空格,光標(biāo)設(shè)為可見并定位在緩沖區(qū)原點(diǎn)(0, 0),而窗口的原點(diǎn)(左上角)與緩沖區(qū)原點(diǎn)置為重合??刂婆_(tái)屏幕緩沖區(qū)的大小、窗口的大小、文本屬性和光標(biāo)的外觀取決于用戶或系統(tǒng)的缺省設(shè)置。

為獲取控制臺(tái)屏幕緩沖區(qū)各種相關(guān)屬性的當(dāng)前值,可分別調(diào)用函數(shù):

GetConsoleScreenBufferInfo;

GetConsoleCursorInfo;

GetConsoleMode。

屏幕緩沖區(qū)光標(biāo)信息用CONSOLE_CURSOR_INFO結(jié)構(gòu)類型的數(shù)據(jù)表示,成員bVisible表示光標(biāo)是否可見,成員dwSize表示光標(biāo)外觀大小,取值范圍為1~100。光標(biāo)可見時(shí),dwSize的取值從100變?yōu)?,光標(biāo)外觀大小從充滿整個(gè)字符單元變?yōu)槌霈F(xiàn)在單元底部的一條水平線。調(diào)用函數(shù)GetConsoleCursorInfo和SetConsoleCursorInfo分別可以獲得和設(shè)置光標(biāo)屬性值。

由高級(jí)控制臺(tái)I/O函數(shù)(如getchar,putchar,printf,scanf等)輸出的字符將輸出在光標(biāo)當(dāng)前位置,同時(shí)光標(biāo)移動(dòng)到下一個(gè)字符輸出位置。

調(diào)用函數(shù):

GetConsoleScreenBufferInfo和SetConsoleCursorPosition,

分別可以獲得和設(shè)置光標(biāo)在屏幕緩沖區(qū)坐標(biāo)系統(tǒng)中的當(dāng)前位置,由此可以控制高級(jí)I/O函數(shù)輸出或回顯字符的位置。

字符屬性分為兩類:顏色屬性和DBCS(Double-Byte Character Set,雙字節(jié)字符集)屬性。表3.14中的符號(hào)常量在wincon.h頭文件中進(jìn)行定義。

表3.14 字符屬性符號(hào)常量表

屬性

含義

FOREGROUND_BLUE

文本顏色包含藍(lán)色

FOREGROUND_GREEN

文本顏色包含綠色

FOREGROUND_RED

文本顏色包含紅色

FOREGROUND_INTENSITY

文本顏色加亮

BACKGROUND_BLUE

背景含藍(lán)色

BACKGROUND_GREEN

背景含綠色

BACKGROUND_RED

背景含紅色

BACKGROUND_INTENSITY

背景加亮

COMMON_LVB_LEADING_BYTE

首字節(jié)

COMMON_LVB_TRAILING_BYTE

末字節(jié)

COMMON_LVB_GRID_HORIZONTAL

首行

COMMON_LVB_GRID_LVERTICAL

左列

COMMON_LVB_GRID_RVERTICAL

右列

COMMON_LVB_REVERSE_VIDEO

翻轉(zhuǎn)前景及背景屬性

COMMON_LVB_UNDERSCORE

下劃線

前綴為FOREGROUND的常量值指定文本顏色(文本的前景色)。前綴為BACKGROUND的常量值指定用于填充字符單元背景的顏色。其他常量值用于DBCS屬性。

應(yīng)用程序可以將前景色和背景色常量值組合起來,獲得不同顏色。例如,下面顏色組合的效果為藍(lán)色背景上的亮青色文本。

FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE

配色問題可以由實(shí)驗(yàn)的輸出試驗(yàn)確定!

如果不指定背景顏色值,那么背景為黑色,而不指定前景顏色值,文本為黑色。例如,下面顏色組合將產(chǎn)生白色背景上的黑色文本效果。

BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED

每個(gè)屏幕緩沖區(qū)字符單元儲(chǔ)存了在“畫”該單元的文本(前景)和背景時(shí)所使用的顏色屬性值。應(yīng)用程序可以分別設(shè)置每個(gè)字符單元的顏色值,并將顏色值存儲(chǔ)在每個(gè)單元CHAR_INFO結(jié)構(gòu)類型數(shù)據(jù)的Attributes成員中。

3.4.2 在屏幕上指定位置輸出信息

有多種方法在屏幕指定位置輸出帶屬性的字符串信息,這里介紹其中四種基本方法。

(1) 用標(biāo)準(zhǔn)輸出函數(shù)(putchar, printf, puts等)輸出字符串信息;

//設(shè)置光標(biāo)位置

SetConsoleCursorPosition(output_handle, new_pos);

//輸出字符串string

printf(“%s”, string);

//在字符串輸出位置填充指定的文本屬性

FillConsoleOutputAttribute(output_handle, new_attributes, strlen(string), new_pos, NULL);

其中output_handle是屏幕緩沖區(qū)句柄,new_pos為COORD類型的變量,存放指定的光標(biāo)位置坐標(biāo),new_attributes為WORD類型的變量,存放指定的文本屬性值,string是字符數(shù)組,存放被輸出的字符串。

(2) 用函數(shù)WriteConsole輸出字符串信息;

//設(shè)置光標(biāo)位置

SetConsoleCursorPosition (output_handle, new_pos);

//設(shè)置文本屬性

SetConsoleTextAttribute(output_handle, new_attributes);

//輸出字符串

WriteConsole(output_handle, string, strlen(string), NULL, NULL);

變量的含義同上。

(3) 用函數(shù)WriteConsoleOutputCharacter輸出字符串信息;

//在指定位置填充與所輸出字符串等長的文本屬性值

FillConsoleOutputAttribute(output_handle, new_attributes, strlen(string), new_pos, NULL);

//在該指定位置輸出字符串

WriteConsoleOutputCharacter(output_handle, string, strlen(string), new_pos, NULL);

(4) 用函數(shù)WriteConsoleOutput輸出字符串信息;

CHAR_INFO * lpBuffer;

COORD pos = {0, 0};

COORD size = { strlen(string), 1};

SMALL_RECT area = {new_pos.X, new_pos.Y, new_pos.X+strlen(string)-1, new_pos.Y};

lpBuffer = (CHAR_INFO *)malloc(size.X * size.Y * sizeof(CHAR_INFO));

for(i=0; i<strlen(string); i++) {

lpBuffer->Char.AsciiChar = string[i];

lpBuffer->Attributes = new_attributes;

}

WriteConsoleOutput(output_handle, lpBuffer, size, pos, &area);

free(&area);

演示并解釋例3.1 menu_ex3_1

這種方法使用起來相對(duì)復(fù)雜一些。基本思想是將輸出信息當(dāng)作一個(gè)矩形字符信息塊,設(shè)置矩形塊的大小size,矩形塊在窗口中的輸出位置area,將矩形塊內(nèi)字符信息存放在一個(gè)動(dòng)態(tài)存儲(chǔ)緩沖區(qū)lpBuffer內(nèi),字符信息包含了字符的碼值和顏色屬性,最后調(diào)用函數(shù)WriteConsoleOutput將lpBuffer中字符塊信息寫到控制臺(tái)屏幕緩沖區(qū)指定位置。

3.4.3 彈出窗口的設(shè)計(jì)

屏幕窗口是個(gè)有限的信息顯示區(qū)域。在文本字符界面下,控制臺(tái)窗口的大小通常設(shè)為80個(gè)字符的寬度和25行字符的高度,即每屏可以顯示2000個(gè)字符。

彈出窗口設(shè)計(jì)的基本思路是:

1、確定輸出信息的屏幕位置和大?。?/p>

2、將新窗口彈出后所要覆蓋的屏幕區(qū)域字符信息讀入到一塊內(nèi)存緩沖區(qū);

3、在新窗口內(nèi)輸出信息,模擬“彈出”效果。

4、彈出窗口內(nèi)的操作完成后,把保存在內(nèi)存緩沖區(qū)的字符信息寫到其原來所在的屏幕位置,彈出窗口消失,屏幕恢復(fù)為窗口彈出之前的外觀。

演示并解釋例3.1 menu_ex3_2

多層彈出窗口自學(xué)

按照這一思路,可以實(shí)現(xiàn)多層彈出窗口。窗口的多層彈出和逐層關(guān)閉,給屏幕信息的維護(hù)帶來了復(fù)雜性。為了便于處理,我們用鏈表來模擬堆棧,實(shí)現(xiàn)彈出窗口的棧式管理。

彈出窗口棧式管理用到以下結(jié)構(gòu)類型。

typedef struct layer_node {

char LayerNo; //彈出窗口層數(shù)

SMALL_RECT rcArea; //彈出窗口區(qū)域坐標(biāo)

CHAR_INFO *pContent; //彈出窗口區(qū)域字符單元原信息存儲(chǔ)緩沖區(qū)

char *pScrAtt; //彈出窗口區(qū)域字符單元原屬性值存儲(chǔ)緩沖區(qū)

struct layer_node *next; //下一結(jié)點(diǎn)的地址

} LAYER_NODE;

利用這種結(jié)構(gòu)類型的數(shù)據(jù)可以模擬出如圖3.10所示的堆棧,對(duì)彈出窗口信息進(jìn)行管理。

圖3.10 彈出窗口信息堆棧

LAYER_NODE結(jié)構(gòu)的5個(gè)成員分別表示了彈出窗口相關(guān)信息。LayerNo表示當(dāng)前彈出窗口的層數(shù);rcArea表示當(dāng)前彈出窗口矩形區(qū)域的位置和大小;pContent指向的動(dòng)態(tài)存儲(chǔ)區(qū)存放被彈出窗口所覆蓋區(qū)域的原字符單元信息,用于當(dāng)前彈出窗口關(guān)閉后恢復(fù)原屏幕窗口信息;pScrAtt指向的動(dòng)態(tài)存儲(chǔ)區(qū)存放內(nèi)容的用途與輸入處理相關(guān),將在下面的輸入處理中進(jìn)行介紹;next存放下層彈出窗口相關(guān)信息的地址。

堆棧棧頂由LAYER_NODE結(jié)構(gòu)指針TopLayer來指示,初值為NULL。系統(tǒng)界面初始化完成之后,屏幕窗口看作第一層彈出窗口,窗口相關(guān)信息用LAYER_NODE結(jié)構(gòu)類型的動(dòng)態(tài)存儲(chǔ)區(qū)存放后入棧,結(jié)構(gòu)指針TopLayer指向棧頂;以后每彈出一層窗口,就執(zhí)行一次入棧操作。關(guān)閉彈出窗口時(shí),用TopLayer指向的LAYER_NODE結(jié)構(gòu)類型數(shù)據(jù)恢復(fù)被覆蓋的屏幕區(qū)域,將TopLayer指向下一層結(jié)點(diǎn),釋放用過的動(dòng)態(tài)存儲(chǔ)區(qū),完成出棧操作。

3.4.4 鍵盤和鼠標(biāo)輸入信息的獲取

ReadConsoleInput函數(shù)原型為:

BOOL WINAPI ReadConsoleINPUT(HANDLE hConsoleInput, PINPUT_RECORD

lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);

功能:用來從控制臺(tái)輸入緩沖區(qū)讀取輸入數(shù)據(jù),并將讀出數(shù)據(jù)從輸入緩沖區(qū)刪除掉。

函數(shù)ReadConsoleInput被調(diào)用時(shí),如果緩沖區(qū)中沒有輸入數(shù)據(jù),函數(shù)將等待下去,直到讀到至少一條記錄后返回。讀到的記錄存放在參數(shù)lpBuffer所指向的內(nèi)存單元。

記錄用INPUT_RECORD結(jié)構(gòu)類型的數(shù)據(jù)來表示;

成員EventType表示事件的類型;

成員Event是聯(lián)合類型,存放事件的具體內(nèi)容。

編程時(shí),需要對(duì)EventType的值為KEY_EVENT(鍵盤輸入)或MOUSE_EVENT(鼠標(biāo)輸入)的兩類事件進(jìn)行處理。

當(dāng)EventType的值為KEY_EVENT時(shí),Event的聯(lián)合成員KeyEvent存放了按鍵相關(guān)信息。KeyEvent是KEY_EVENT_RECORD結(jié)構(gòu)類型,其成員bKeyDown表明鍵是被按下(TRUE)還是被釋放(FALSE),成員wRepeatCount表明按鍵重復(fù)的次數(shù),成員wVirtualKeyCode存放按鍵的虛擬鍵碼,成員wVirtualScanCode存放按鍵的虛擬掃描碼,成員uChar存放按鍵的ASCII碼或Unicode碼(取決于系統(tǒng)所采用的字符集),成員dwControlKeyState表示有哪些控制鍵被同時(shí)按下。我們每按一次鍵會(huì)產(chǎn)生兩個(gè)事件記錄,一個(gè)記錄表示鍵被按下,另一條記錄表示鍵被釋放。常用鍵的各種碼值參見附錄。

當(dāng)EventType的值為MOUSE_EVENT時(shí),Event的聯(lián)合成員MouseEvent存放了鼠標(biāo)操作相關(guān)信息。MOUSEEvent是MOUSE_EVENT_RECORD結(jié)構(gòu)類型,其成員dwMousePosition存放了鼠標(biāo)操作時(shí)的坐標(biāo)位置,表明鼠標(biāo)處于窗口中的某行和某列的字符單元位置上,成員dwButtonState表明鼠標(biāo)哪些按鈕被按下,取值可為下面符號(hào)常量之一或多個(gè)符號(hào)常量的組合值:

FROM_LEFT_1ST_BUTTON_PRESSED值為1,表示按下了鼠標(biāo)最左邊按鈕;

RIGHTMOST_BUTTON_PRESSED值為2,表示按下了鼠標(biāo)最右邊按鈕;

FROM_LEFT_2ND_BUTTON_PRESSED值為4,表示按下了鼠標(biāo)左起第二個(gè)按鈕;

FROM_LEFT_3RD_BUTTON_PRESSED值為8,表示按下了鼠標(biāo)左起第三個(gè)按鈕;

FROM_LEFT_4TH_BUTTON_PRESSED值為16,表示按下了鼠標(biāo)左起第四個(gè)按鈕。

成員dwControlKeyState表示在鼠標(biāo)事件發(fā)生時(shí)有哪些控制鍵被同時(shí)按下,成員dwEventFlags表示鼠標(biāo)事件的具體類型,取值為以下符號(hào)常量:

MOUSE_MOVED值為1,表示鼠標(biāo)移動(dòng)事件;

DOUBLE_CLICK值為2,表示鼠標(biāo)雙擊事件;

MOUSE_WHEELED值為4,表示鼠標(biāo)滾輪滾動(dòng)事件。

3.4.5 輸入處理(略)

(1) 鍵盤輸入處理

按照表3.15進(jìn)行處理,對(duì)其他按鍵不予響應(yīng)。

表3.15 主界面下的鍵盤輸入處理設(shè)計(jì)

按鍵

系統(tǒng)響應(yīng)

F1

執(zhí)行幫助菜單下的幫助主題子菜單對(duì)應(yīng)功能模塊

Alt+X

執(zhí)行文件菜單下的退出系統(tǒng)子菜單對(duì)應(yīng)功能模塊

Alt+F

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記文件菜單項(xiàng)并彈出文件菜單的子菜單

Alt+M

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)維護(hù)菜單項(xiàng)并彈出數(shù)據(jù)維護(hù)菜單的子菜單

Alt+Q

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)查詢菜單項(xiàng)并彈出數(shù)據(jù)查詢菜單的子菜單

Alt+S

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)統(tǒng)計(jì)菜單項(xiàng)并彈出數(shù)據(jù)統(tǒng)計(jì)菜單的子菜單

Alt+H

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記幫助菜單項(xiàng)并彈出幫助菜單的子菜單

向左←

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記左側(cè)菜單項(xiàng)

向右→

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記右側(cè)菜單項(xiàng)

向下↓

彈出當(dāng)前菜單項(xiàng)的子菜單

f或F

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記文件菜單項(xiàng)并彈出文件菜單的子菜單

m或M

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)維護(hù)菜單項(xiàng)并彈出數(shù)據(jù)維護(hù)菜單的子菜單

q或Q

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)查詢菜單項(xiàng)并彈出數(shù)據(jù)查詢菜單的子菜單

s或S

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記數(shù)據(jù)統(tǒng)計(jì)菜單項(xiàng)并彈出數(shù)據(jù)統(tǒng)計(jì)菜單的子菜單

h或H

清除當(dāng)前選中菜單項(xiàng)標(biāo)記,標(biāo)記幫助菜單項(xiàng)并彈出幫助菜單的子菜單

回車

彈出當(dāng)前菜單項(xiàng)的子菜單

鍵盤輸入處理時(shí),要考慮輸入處理的優(yōu)先級(jí),應(yīng)先響應(yīng)快捷鍵,再響應(yīng)組合鍵,最后響應(yīng)單鍵。以Alt組合鍵為例,判斷組合鍵的方法為:

ReadConsoleInput(hIn, &inRec, 1, &res); //從輸入緩沖區(qū)讀取一條輸入記錄

if (inRec.EventType == KEY_EVENT && inRec.Event.KeyEvent.bKeyDown) {

//輸入事件類別為KEY_EVENT,且事件由鍵被按下所觸發(fā)

vkc = inRec.Event.KeyEvent.wVirtualKeyCode; //提取虛擬鍵碼

asc = inRec.Event.KeyEvent.uChar.AsciiChar; //提取ASCII碼

if (inRec.Event.KeyEvent.dwControlKeyState //如果左或右Alt鍵被按下

& (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {

…… //進(jìn)一步判斷與Alt組合的另一個(gè)鍵,并做響應(yīng)處理

}

…… //非Alt組合鍵的響應(yīng)處理

}

常用控制鍵所對(duì)應(yīng)的符號(hào)常量在wincon.h頭文件中進(jìn)行了定義,如表3.16所示。

表3.16 控制鍵對(duì)應(yīng)符號(hào)常量表

鍵名

符號(hào)常量

鍵名

符號(hào)常量

右Alt

RIGHT_ALT_PRESSED

1

左Alt

LEFT_ALT_PRESSED

2

右Ctrl

RIGHT_CTRL_PRESSED

4

左Ctrl

LEFT_CTRL_PRESSED

8

左右Shift

SHIFT_PRESSED

16

數(shù)字鎖定

NUMLOCK_ON

32

屏幕鎖定

SCROLLLOCK_ON

64

大寫鎖定

CAPSLOCK_ON

128

(2) 鼠標(biāo)輸入處理

熱區(qū)本是網(wǎng)頁設(shè)計(jì)中用到的一個(gè)概念,是指網(wǎng)頁上建有鏈接的區(qū)域。我們將熱區(qū)這個(gè)概念借用到程序設(shè)計(jì)中人機(jī)交互界面的設(shè)計(jì)上來,用來指界面上需要對(duì)鼠標(biāo)事件(包括鼠標(biāo)移動(dòng)、滾輪轉(zhuǎn)動(dòng)、雙擊和任意一到多個(gè)鍵的按下)產(chǎn)生反應(yīng)的區(qū)域。

基于這一思想,可用一個(gè)字符(8個(gè)二進(jìn)制位)來表示窗口中某個(gè)字符單元的屬性。如圖3.12所示,這8個(gè)二進(jìn)制位分為三段:0~1比特為A1,2~5比特為A2,6~7比特為A3。A1的取值范圍為0~3,用來表示字符單元的“高度”,即該字符單元上彈出窗口的層數(shù),0表示字符單元處于系統(tǒng)主界面層,沒有彈出窗口覆蓋該字符單元,這樣彈出窗口的層數(shù)最多可到3層;A2取值范圍為0~15,用來表示字符單元的熱區(qū)編號(hào),0表示字符單元不屬于熱區(qū),這樣同一層上的熱區(qū)最多可為15個(gè);A3取值范圍為0~3,在A2取值不為0時(shí)用來表示字符單元的熱區(qū)類型,0代表按鈕類型,1代表輸入框類型,2代表下拉選框類型,3保留備用。不同類型的熱區(qū)被鼠標(biāo)擊中時(shí),系統(tǒng)可以分別進(jìn)行處理。本課程設(shè)計(jì)中,字符單元的屬性用8個(gè)二進(jìn)制位來存放,剛好夠用。在其他應(yīng)用程序開發(fā)中,如果彈出菜單超過3層,或某層窗口中熱區(qū)超過15個(gè),或熱區(qū)類型超過4類,可以考慮用16個(gè)二進(jìn)制位來存放字符單元屬性。

7

6

5

4

3

2

1

0

A3

A2

A1

圖3.12 字符單元屬性的表示

前面在介紹彈出窗口設(shè)計(jì)時(shí),彈出窗口的棧式管理用到以下結(jié)構(gòu)類型:

typedef struct layer_node {

char LayerNo; //彈出窗口層數(shù)

SMALL_RECT rcArea; //彈出窗口區(qū)域坐標(biāo)

CHAR_INFO *pContent; //彈出窗口區(qū)域字符單元原信息存儲(chǔ)緩沖區(qū)

char *pScrAtt; //彈出窗口區(qū)域字符單元原屬性值存儲(chǔ)緩沖區(qū)

struct layer_node *next; //下一結(jié)點(diǎn)的地址

} LAYER_NODE;

其中,結(jié)構(gòu)成員pScrAtt用來指向一個(gè)動(dòng)態(tài)存儲(chǔ)區(qū),該存儲(chǔ)區(qū)存放被彈出窗口所覆蓋字符單元的原先屬性值,在彈出窗口關(guān)閉時(shí)用于恢復(fù)窗口彈出前屏幕字符單元的屬性。

系統(tǒng)界面初始化完成之后,屏幕顯示系統(tǒng)的主界面(如圖3.9所示)。用一個(gè)字符數(shù)組ScrAtt存放屏幕上所有字符單元的屬性值,字符單元的坐標(biāo)X和Y與存放其屬性值的數(shù)組元素下標(biāo)n的關(guān)系為:

n = Y × 屏幕緩沖區(qū)的寬度 + X

主界面中只有5個(gè)主菜單項(xiàng)顯示區(qū)域?yàn)闊釁^(qū),依次編號(hào)1~5,熱區(qū)類型為按鈕型。此后,如果有窗口彈出(彈出菜單也是彈出窗口),則將窗口所覆蓋區(qū)域字符單元的信息和屬性分別保存起來,執(zhí)行彈出窗口信息入棧操作,然后在彈出窗口區(qū)域輸出提示信息,將彈出窗口字符單元的屬性值寫入數(shù)組ScrAtt對(duì)應(yīng)元素以設(shè)置熱區(qū)。鼠標(biāo)輸入處理時(shí),取鼠標(biāo)所在字符單元的屬性值,根據(jù)字符單元的層數(shù)、熱區(qū)編號(hào)和熱區(qū)類型,結(jié)合鼠標(biāo)事件類型做出相應(yīng)處理。當(dāng)彈出窗口關(guān)閉時(shí),用所保存的彈出窗口區(qū)域字符單元原先的屬性值修改數(shù)組ScrAtt對(duì)應(yīng)元素值,恢復(fù)窗口彈出前屏幕字符單元的屬性,最后執(zhí)行彈出窗口信息出棧操作。

3.4.6 菜單操作與系統(tǒng)功能函數(shù)的調(diào)用

按照概要設(shè)計(jì),系統(tǒng)功能分為五個(gè)模塊,各模塊所包含的子模塊共有22個(gè),分別用22個(gè)函數(shù)實(shí)現(xiàn)相應(yīng)功能。其中,數(shù)據(jù)加載函數(shù)和界面初始化函數(shù)只在系統(tǒng)啟動(dòng)時(shí)執(zhí)行一次,以后不再執(zhí)行。其余20個(gè)函數(shù)可以通過菜單操作或快捷鍵執(zhí)行相應(yīng)功能。

例3.3 在圖3.9所示的主界面下,實(shí)現(xiàn)菜單操作與系統(tǒng)功能函數(shù)的調(diào)用。本例中給出了函數(shù)SysRun和函數(shù)ExeFunction的定義,分別用于菜單操作和系統(tǒng)功能函數(shù)的調(diào)用。例子中調(diào)用了例3.1和例3.2中的函數(shù),而其余函數(shù)的定義沒有給出。

#include "dorm.h"

void SysRun( )

{

INPUT_RECORD inRec;

DWORD res;

COORD pos = {0, 0};

BOOL bRet = TRUE;

int i, loc, num;

int cNo, cAtt; //cNo:字符單元層號(hào), cAtt:字符單元屬性

char vkc, asc; //vkc:虛擬鍵代碼, asc:字符的ASCII碼值

while (bRet) { // 循環(huán)

ReadConsoleInput(hIn, &inRec, 1, &res);

if (inRec.EventType == MOUSE_EVENT) {

pos = inRec.Event.MouseEvent.dwMousePosition; /* pos 是坐標(biāo) */

cNo = ScrAtt[pos.Y * ScrCol + pos.X] & 3;

cAtt = ScrAtt[pos.Y * ScrCol + pos.X] >> 2;

if (cNo == 0) {

if (cAtt > 0 && cAtt != SelMenu && TopLayer->LayerNo > 0) {

PopOff();

SelSMenu = 0;

PopMenu(cAtt);

}

}

else if (cAtt > 0) {

TagSMenu(cAtt);

}

if (inRec.Event.MouseEvent.dwButtonState

== FROM_LEFT_1ST_BUTTON_PRESSED) {

if (cNo == 0) {

if (cAtt > 0) {

PopMenu(cAtt);

}

else if (TopLayer->LayerNo > 0) {

PopOff();

SelSMenu = 0;

}

}

else {

if (cAtt > 0) {

PopOff();

SelSMenu = 0;

bRet = ExeFunction(SelMenu, cAtt);

}

}

}

else if (inRec.Event.MouseEvent.dwButtonState

== RIGHTMOST_BUTTON_PRESSED) {

if (cNo == 0) {

PopOff();

SelSMenu = 0;

}

}

}

else if (inRec.EventType == KEY_EVENT

&& inRec.Event.KeyEvent.bKeyDown) {

vkc = inRec.Event.KeyEvent.wVirtualKeyCode;

asc = inRec.Event.KeyEvent.uChar.AsciiChar;

//系統(tǒng)快捷鍵的處理

if (vkc == 112) { //F1鍵

if (TopLayer->LayerNo != 0) {

PopOff();

SelSMenu = 0;

}

bRet = ExeFunction(5, 1); //F1幫助主題

}

else if (inRec.Event.KeyEvent.dwControlKeyState

& (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {

switch (vkc) { //組合鍵Alt+字母

case 88: if (TopLayer->LayerNo != 0) {

PopOff();

SelSMenu = 0;

}

bRet = ExeFunction(1,4); break; //Alt+X 退出

case 70: PopMenu(1); break; //Alt+F

case 77: PopMenu(2); break; //Alt+M

case 81: PopMenu(3); break; //Alt+Q

case 83: PopMenu(4); break; //Alt+S

case 72: PopMenu(5); break; //Alt+H

}

}

else if (asc == 0) { //方向鍵的處理

if (TopLayer->LayerNo == 0) { //未彈出子菜單時(shí)

switch (vkc) { //方向鍵(左、右、下)的處理

case 37: SelMenu--;

if (SelMenu == 0) {

SelMenu = 5;

}

TagMenu(SelMenu); break;

case 39: SelMenu++;

if (SelMenu == 6) {

SelMenu = 1;

}

TagMenu(SelMenu); break;

case 40: PopMenu(SelMenu);

TagSMenu(1); break;

}

}

else { //已彈出子菜單時(shí)

for (loc=0,i=1; i<SelMenu; i++) {

loc += cSMenu[i-1];

} //找到子菜單第一項(xiàng)在子菜單數(shù)組中的位置(下標(biāo))

switch (vkc) { //方向鍵(左、右、上、下)的處理

case 37: SelMenu--;

if (SelMenu < 1) {

SelMenu = 5;

}

TagMenu(SelMenu); PopOff();

PopMenu(SelMenu); TagSMenu(1);

break;

case 38: num = SelSMenu - 1;

if (num < 1) {

num = cSMenu[SelMenu-1];

}

if (strlen(SMenu[loc+num-1]) == 0) {

num--;

}

TagSMenu(num); break;

case 39: SelMenu++;

if (SelMenu > 5) {

SelMenu = 1;

}

TagMenu(SelMenu); PopOff();

PopMenu(SelMenu); TagSMenu(1);

break;

case 40: num = SelSMenu + 1;

if (num > cSMenu[SelMenu-1]) {

num = 1;

}

if (strlen(SMenu[loc+num-1]) == 0) {

num++;

}

TagSMenu(num); break;

}

}

}

else if ((asc-vkc == 0) || (asc-vkc == 32)){ //按下普通鍵

if (TopLayer->LayerNo == 0) { //未彈出子菜單時(shí)

switch (vkc) {

case 70: PopMenu(1); break; //f或F

case 77: PopMenu(2); break; //m或M

case 81: PopMenu(3); break; //q或Q

case 83: PopMenu(4); break; //s或S

case 72: PopMenu(5); break; //h或H

case 13: PopMenu(SelMenu); //回車

TagSMenu(1); break;

}

}

else { //已彈出子菜單時(shí)的鍵盤輸入處理

if (vkc == 27) { //按下ESC鍵時(shí), 關(guān)閉子菜單

PopOff();

SelSMenu = 0;

}

else if(vkc == 13) { //|| vkc == 32

num = SelSMenu;

PopOff();

SelSMenu = 0;

bRet = ExeFunction(SelMenu, num);

}

else {

for (loc=0,i=1; i<SelMenu; i++) {

loc += cSMenu[i-1];

}

for (i=loc; i<loc+cSMenu[SelMenu-1]; i++) {

if (strlen(SMenu[i])>0 && vkc==SMenu[i][1]) {

PopOff();

SelSMenu = 0;

bRet = ExeFunction(SelMenu, i-loc+1);

}

}

}

}

}

}

}

}

BOOL ExeFunction(int m, int s)

{

BOOL bRet = TRUE;

BOOL (*pFunction[cSMenu[0]+cSMenu[1]+cSMenu[2]+cSMenu[3]+cSMenu[4]])(void);

int i, loc;

//pFunction

pFunction[0] = DataSave;

pFunction[1] = DataBackup;

pFunction[2] = DataRestore;

pFunction[3] = SySexit;

pFunction[4] = MaintainSex;

pFunction[5] = MaintainType;

pFunction[6] = NULL;

pFunction[7] = MaintainDorm;

pFunction[8] = MaintainStu;

pFunction[9] = MaintainCharge;

pFunction[10] = QuerySex;

pFunction[11] = QueryType;

pFunction[12] = NULL;

pFunction[13] = QueryDorm;

pFunction[14] = QueryStu;

pFunction[15] = QueryCharge;

pFunction[16] = StatIn;

pFunction[17] = StatType;

pFunction[18] = StatCharge;

pFunction[19] = StatUncharge;

pFunction[20] = HelpTopic;

pFunction[21] = NULL;

pFunction[22] = AboutDorm;

for (i=1,loc=0; i<m; i++) {

loc += cSMenu[i-1];

}

loc += s - 1;

if (pFunction[loc] != NULL) {

bRet = (*pFunction[loc])();

}

return bRet;

}

演示并解釋例3.1 menu_ex3_2

作者:liaojiaohong https://www.bilibili.com/read/cv12993546 出處:bilibili

以上就是關(guān)于pos機(jī)交互過程,CodeBlock下的人機(jī)交互界面設(shè)計(jì)的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)交互過程的知識(shí),希望能夠幫助到大家!

轉(zhuǎn)發(fā)請(qǐng)帶上網(wǎng)址:http://www.dsth100338.com/newsone/67210.html

你可能會(huì)喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 babsan@163.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。