是否可以在没有 GUI 的情况下使用程序的 GUI 功能?

逆向工程 艾达 拆卸 视窗 调试 记忆
2021-07-10 11:21:55

是否可以在不使用 GUI 的情况下直接使用/调用程序的 GUI 功能(以编程方式,而不是通过键盘输入)?

例如,一个程序在级联子菜单中嵌套太深:

直接触发?

是否可以直接/以编程方式使用/触发这些菜单项中的任何一个...就像您使用 GUI 直接单击它一样

我想有点像逆向工程的“API”。我认为它需要某种实时调试来查看单击 GUI 项时程序到达或调用内存的位置。然后希望在你看到那个位置之后,你可以随意调用它,或者记录程序的消息/排队来执行它,然后你可以随意重播,能够使用或激活程序的能力而无需触摸 GUI。

另一个简单的例子:

记事本图形用户界面

在 Windows 记事本中,启用“自动换行”的唯一方法是在菜单栏菜单中单击它(键盘导航相同)。但是在 GUI 幕后,内存中的某个地方有一个函数可以被调用或设置标志位。

我想知道是否可以自己(以编程方式)直接触发/调用这些能力/功能,手动拉动 GUI 木偶字符串,在不使用 GUI 的情况下激活字符串另一端的功能。

由于 GUI 基本上只是一个点击式地图,字符串附加到内存中的后端函数/代码,我认为这可能是可能的,除非程序内存保护。

注意:我是从逆向工程的角度 100% 提出这个问题的,而不是关于如何通过宏/脚本/自动化来做到这一点。我很清楚 AutoHotkey、AutoIt 等工具,但这不是我问这个问题的原因。

2个回答

如果所述 gui 在某个调试器下,不确定您正在寻找什么方法

你可以简单地绕过一个补丁

或者,如果您在 gui 的 wndproc 线程下,您可以使用 apis
(例如,用于检查记事本中的菜单自动换行,请使用 CheckMenuItem();)

或使用最古老的技巧 SendMessage From an external App a demo and src is below

在此处输入图片说明

src 在 32 位 win 7 x86 机器上使用 2017 社区 32 位编译

cl /Zi /W4 /analyze /Od /EHsc /nologo MENU.CPP /link /release

源文件

#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"user32.lib")
#define MAXSUBMENUS 100
int main(void) {
    printf("lets wrappify the notes pad\n");
    HWND notewnd = FindWindowA("Notepad", NULL);
    if (notewnd != NULL) {
        printf("notepad handle is %p\n", notewnd);
        HMENU menubar = GetMenu(notewnd);
        if (menubar != NULL) {
            printf("menubar handle is %p\n", menubar);
            int menuitemcount = GetMenuItemCount(menubar);
            printf("menubar contains %d Items\n", menuitemcount);
            if (menuitemcount > MAXSUBMENUS) { menuitemcount = MAXSUBMENUS; }
            HMENU submenus[MAXSUBMENUS] = { 0 };
            int submenuitemcount[MAXSUBMENUS] = { 0 };
            for (int i = 0; i < menuitemcount; i++) {
                submenus[i] = GetSubMenu(menubar, i);
                if (submenus[i] != NULL) {
                    submenuitemcount[i] = GetMenuItemCount(submenus[i]);
                    printf("submenu[%d] handle is %p and contains %d Items\n",
                        i, submenus[i], submenuitemcount[i]);
                }
            }
            for (int i = 0; i < submenuitemcount[2]; i++) {
                printf("format menu bypos %d ID = %u\n", i, 
                    GetMenuItemID(submenus[2], i));
            }
            printf ("%x\n" , SendMessage(notewnd,WM_COMMAND,
            MAKEWPARAM(GetMenuItemID(submenus[2],0),0),(LPARAM)NULL));
        }
    }
    return 0;
}

或者作为extremecoder指出使用各种可用的包

编辑 0xc0000022 的评论

不知道 sublime 有什么特别之处 从未使用过它,只是安装了它并根据 sublime 的 PID 运行了一个蛮子它似乎可以工作我从 spy++ 收集菜单 ID 用于演示目的,但从输出中可以看出,可以看到菜单的数量在 sublimes 主窗口句柄的情况下,项目计数为 10

代码如下

#include <windows.h>
#include <stdio.h>
int  GetHwnds(DWORD InPID, HWND *somewind){
    HWND hCurWnd = NULL;
    int i =0;
    do {
        hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
        DWORD pid = 0;        
        GetWindowThreadProcessId(hCurWnd, &pid);
        if (pid == InPID){
            somewind[i++] = hCurWnd;
            printf("Found hWnd %p\n", hCurWnd);
        }
    }
    while (hCurWnd != NULL);
    return i;
}
void main(int argc,char *argv[]) {
    if(argc !=2){
        printf ("usage %s pid",argv[0]);
        exit(0);
    }
    HWND subyuck[0x50] = {NULL};    
    int yucks = GetHwnds(atoi(argv[1]),subyuck);
    for(int i=0;i<yucks;i++){
        if(subyuck[i] != NULL){
            printf("menu %p MenuItemCount %d\n",GetMenu(subyuck[i]),GetMenuItemCount(GetMenu(subyuck[i])));
            SendMessage(subyuck[i],WM_COMMAND,MAKEWPARAM(436,0),MAKELPARAM(0,0));
        }
    }
}

输出

C:\Users\XXX\Desktop\yucketyyuck>cl /Zi /W4 /analyze /Od yucketyyuck.cpp /link /release user32.lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27025.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

yucketyyuck.cpp
Microsoft (R) Incremental Linker Version 14.16.27025.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:yucketyyuck.exe
/debug
/release
user32.lib
yucketyyuck.obj

C:\Users\XXX\Desktop\yucketyyuck>tasklist |grep -i sub*
sublime_text.exe              3272 Console                    1     18,684 K

C:\Users\XXX\Desktop\yucketyyuck>yucketyyuck.exe 3272
Found hWnd 002104DE
Found hWnd 00240586
Found hWnd 00070322 <<<<<<<<<<<<<< gui thread 
Found hWnd 001D02AA
menu 00000000 MenuItemCount -1
menu 00000000 MenuItemCount -1
menu 001A033D MenuItemCount 10 <<<<<<<<<<<<<< 
menu 00000000 MenuItemCount -1

一个 gif 以防万一

在此处输入图片说明

通常 ResHack 应该显示 Menu 的 Control ID,
但在 sublime text reshack 不显示菜单的情况下,
我没有检查原因,但我刚刚检索了所有 ControlIDS(其中 632 个),您可以使用 SendMessage WM_COMMAND->wNotify

使用下面的代码

#include <windows.h>
#include <stdio.h>
#define MAXANY 0x100

void enumenu(HMENU hMenu) {

    for (int i = 0; i < GetMenuItemCount(hMenu); i++)
    {
        char menustring[MAXANY] = { 0 };
        MENUITEMINFO mii = { 0 };
        mii.cbSize = sizeof(MENUITEMINFO);
        mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;
        mii.dwTypeData = menustring;
        mii.cch = MAXANY;
        GetMenuItemInfoA(hMenu, i, TRUE, &mii);
        printf("%8u   ", mii.wID);
        if( (mii.fState & MFS_CHECKED) == MFS_CHECKED)
            printf("X   ");
        else 
            printf("    ");

        if (mii.fType == MFT_SEPARATOR)
        {
            printf("------------------\n");
        }
        if (mii.fType == MFT_STRING)
        {
            printf("---%s\n", menustring);
        }
        if (mii.hSubMenu != NULL)
        {
            enumenu(mii.hSubMenu);
        }
    }
}

int  GetHwnds(DWORD InPID, HWND *somewind) {
    HWND hCurWnd = NULL;
    int i = 0;
    do {
        hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
        DWORD pid = 0;
        GetWindowThreadProcessId(hCurWnd, &pid);
        if (pid == InPID) {
            if (i > MAXANY) { return i; }
            somewind[i++] = hCurWnd;
        }
    } while (hCurWnd != NULL);
    return i;
}
void main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("usage %s pid", argv[0]);
        exit(0);
    }
    HWND subyuck[MAXANY] = { NULL };
    int yucks = GetHwnds(atoi(argv[1]), subyuck);
    for (int i = 0; i < yucks; i++) {
        if (subyuck[i] != NULL) {
            HMENU submenu = GetMenu(subyuck[i]);
            enumenu(submenu);

        }
    }
}

和菜单 controlIDS(在 WordWrap 的情况下检查为 436,由 X 显示)

  590370       ---&File
       0       ---&New File     Ctrl+N
       1       ---&Open Fileà   Ctrl+O
       2       ---Open Folderà
 1049112       ---Open &Recent
       3       ---Reopen Closed File    Ctrl+Shift+T
       4       ------------------
       5       ---Restored from abyss  (all invisible menu items with this name are dittoed with ""
       6       ""
       7       ""
       8       ""
       9       ""
      10       ""
      11       ""
      12       ""
      13       ""
      14       ""
      15       ""
      16       ""
      17       ""
      18       ""
      19       ""
      20       ""
      21       ""
      22       ""
      23       ---Clear Items
  262656       ---Reopen with Encoding
            removed allen coding IDS
      97       ---Save &Asà     Ctrl+Shift+S
      98       ---Save A&ll
      99       ------------------
     100       ---New &Window   Ctrl+Shift+N
     101       ---Close Window  Ctrl+Shift+W
     102       ------------------
     103       ---&Close File   Ctrl+W
     104       ---Re&vert File
     105       ---Close All Files
     106       ------------------
     107       ---E&xit
 1245462       ---&Edit
     108       ---&Undo Ctrl+Z
     109       ---&Redo Ctrl+Y
  590368       ---Undo Selection
     110       ---Soft Undo     Ctrl+U
     111       ---Soft Redo     Ctrl+Shift+U
     112       ------------------
     113       ---Cu&t  Ctrl+X
     114       ---&Copy Ctrl+C
     115       ---&Paste        Ctrl+V
     116       ---Paste and &Indent     Ctrl+Shift+V
     117       ---Paste from History    Ctrl+K, Ctrl+V
     118       ------------------
  262624       ---&Line
     119       ---Indent        Ctrl+]
     120       ---Unindent      Ctrl+[
     121       ---Reindent
     122       ---Swap Line Up  Ctrl+Shift+Up
     123       ---Swap Line Down        Ctrl+Shift+Down
     124       ---Duplicate Line        Ctrl+Shift+D
     125       ---Delete Line   Ctrl+Shift+K
     126       ---Join Lines    Ctrl+J
  590472       ---Co&mment
     127       ---Toggle Comment        Ctrl+/
     128       ---Toggle Block Comment  Ctrl+Shift+/
  197082       ---&Text
     129       ---Revert Modification   Ctrl+K, Ctrl+Z
     130       ""
     131       ------------------
     132       ---Insert Line Before    Ctrl+Shift+Enter
     133       ---Insert Line After     Ctrl+Enter
     134       ------------------
     135       ---Delete Word Forward   Ctrl+Delete
     136       ---Delete Word Backward  Ctrl+Backspace
     137       ---Delete Line   Ctrl+Shift+K
     138       ---Delete to End Ctrl+K, Ctrl+K
     139       ---Delete to Beginning   Ctrl+K, Ctrl+Backspace
     140       ------------------
     141       ---Transpose     Ctrl+T
  262582       ---Tag
     142       ---Close Tag     Alt+.
     143       ---Expand Selection to Tag       Ctrl+Shift+A
     144       ---Wrap Selection With Tag       Alt+Shift+W
  262672       ---Mark
     145       ---Set Mark      Ctrl+K, Ctrl+Space
     146       ---Select to Mark        Ctrl+K, Ctrl+A
     147       ---Delete to Mark        Ctrl+K, Ctrl+W
     148       ---Swap with Mark        Ctrl+K, Ctrl+X
     149       ---Clear Mark    Ctrl+K, Ctrl+G
     150       ------------------
     151       ---Yank  Ctrl+K, Ctrl+Y
  262674       ---Code Folding
     152       ---Fold  Ctrl+Shift+[
     153       ---Unfold        Ctrl+Shift+]
     154       ---Unfold All    Ctrl+K, Ctrl+J
     155       ------------------
     156       ---Fold All      Ctrl+K, Ctrl+1
       yyyyyyyyyyyyyyyyyyyyyyy
     165       ------------------
     166       ---Fold Tag Attributes   Ctrl+K, Ctrl+T
  131614       ---Convert C&ase
     167       ---Title Case
     168       ---Upper Case    Ctrl+K, Ctrl+U
     169       ---Lower Case    Ctrl+K, Ctrl+L
     170       ---Swap Case
  197238       ---Wrap
     171       ---Wrap Paragraph at Ruler       Alt+Q
      zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
     178       ---Show Completions      Ctrl+Space
     179       ------------------
     180       ---&Sort Lines   F9
     181       ---Sort Lines (Case Sensitive)   Ctrl+F9
  328312       ---Permute Lines
     182       ---Reverse
     183       ---Unique
     184       ---Shuffle
  131644       ---Permute Selections
     185       ---Sort
     186       ---Sort (Case Sensitive)
     187       ---Reverse
     188       ---Unique
     189       ---Shuffle
     190       ""
  131646       ---&Selection
     191       ---Split into Lines      Ctrl+Shift+L
     192       ---Add Previous Line     Ctrl+Alt+Up
     193       ---Add Next Line Ctrl+Alt+Down
     194       ---Single Selection      Escape
     195       ---Invert Selection
     196       ------------------
     197       ---Select All    Ctrl+A
     198       ---Expand Selection to Line      Ctrl+L
         tttttttttttttttttttttttttt
  131648       ---F&ind
     205       ---Findà Ctrl+F
     206       ---Find Next     F3
     207       ---Find Previous Shift+F3
     208       ---Incremental Find      Ctrl+I
     209       ------------------
     210       ---Replaceà      Ctrl+H
     211       ---Replace Next  Ctrl+Shift+H
     212       ------------------
     213       ---Quick Find    Ctrl+F3
     214       ---Quick Find All        Alt+F3
     215       ---Quick Add Next        Ctrl+D
     216       ---Quick Skip Next       Ctrl+K, Ctrl+D
     217       ------------------
     218       ---Use Selection for Find        Ctrl+E
     219       ---Use Selection for Replace     Ctrl+Shift+E
     220       ------------------
     221       ---Find in Filesà        Ctrl+Shift+F
  131692       ---Find &Results
     222       ---Show Results Panel
     223       ---
     224       ---Previous Result
  131716       ---&View
  131690       ---Side Bar
     225       ---Hide Side Bar Ctrl+K, Ctrl+B
     226       ------------------
     227       ---Show Open Files
     228       ---Hide Minimap
     229       ---Hide Tabs
     230       ---Hide Status Bar
     231       ---Hide Menu
     232       ---Show Console  Ctrl+`
     233       ------------------
     234       ---Enter Full Screen     F11
     235       ---Enter Distraction Free Mode   Shift+F11
     236       ------------------
  131688       ---&Layout
     237       ---Single        Alt+Shift+1
     238       ---Columns: 2    Alt+Shift+2
     239       ---Columns: 3    Alt+Shift+3
     240       ---Columns: 4    Alt+Shift+4
     241       ---Rows: 2       Alt+Shift+8
     242       ---Rows: 3       Alt+Shift+9
     243       ---Grid: 4       Alt+Shift+5
  131686       ---Groups
     244       ---Move File to New Group        Ctrl+K, Ctrl+Up
     245       ---New Group     Ctrl+K, Ctrl+Shift+Up
     246       ---Close Group   Ctrl+K, Ctrl+Down
     247       ------------------
     248       ---Max Columns: 1
     249       ---Max Columns: 2
     250       ---Max Columns: 3
     251       ---Max Columns: 4
     252       ---Max Columns: 5
  131684       ---&Focus Group
     253       ---Next  Ctrl+K, Ctrl+Right
     254       ---Previous      Ctrl+K, Ctrl+Left
     255       ------------------
     256       ---Group 1       Ctrl+1
     257       ""
     258       ""
     259       ""
  197250       ---&Move File to Group
     260       ---Next  Ctrl+K, Ctrl+Shift+Right
     261       ---Previous      Ctrl+K, Ctrl+Shift+Left
     262       ------------------
     263       ---Group 1       Ctrl+Shift+1
     264       ""
     265       ""
     266       ""
     267       ------------------
  131682       ---&Syntax
  131680       ---Open all with current extension as...
      uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
   66212       ---&Indentation
     417       ---Indent Using Spaces
     418       ------------------
     419       ---Tab Width: 1
     420       ---Tab Width: 2
     421       ---Tab Width: 3
     422   X   ---Tab Width: 4
     423       ---Tab Width: 5
     424       ---Tab Width: 6
     425       ---Tab Width: 7
     426       ---Tab Width: 8
     427       ------------------
     428       ---Guess Settings From Buffer
     429       ------------------
     430       ---Convert Indentation to Spaces
     431       ---Convert Indentation to Tabs
   66214       ---Li&ne Endings
     432   X   ---Windows
     433       ---Unix
     434       ---Mac OS 9
     435       ------------------
     436   X   ---&Word Wrap       <<<<<<<<<<<<<<<<<<<<<<<<<
   66216       ---Word Wrap Column
     437   X   ---Automatic
     438       ------------------
     439       ---70
     440       ---72
     441       ---78
     442       ---80
     443       ---100
     444       ---120
   66219       ---Ruler
     445   X   ---None
     446       ------------------
     447       ---70
     448       ---72
     449       ---78
     450       ---80
     451       ---100
     452       ---120
     453       ------------------
     454       ---Spell Check   F6
     455       ---Next Misspelling      Ctrl+F6
     456       ---Prev Misspelling      Ctrl+Shift+F6
   66221       ---Dictionary
     457       ---en_GB
     458   X   ---en_US
   66223       ---&Goto
     459       ---Goto &Anythingà       Ctrl+P
     460       ------------------
     461       ---Goto Symbolà  Ctrl+R
     462       ---Goto Symbol in Projectà       Ctrl+Shift+R
     463       ---Goto Definitionà      F12
     464       ---Goto Referenceà       Shift+F12
     465       ---Goto Lineà    Ctrl+G
     466       ------------------
     467       ---Next Modification     Ctrl+.
     468       ---Previous Modification Ctrl+,
     469       ------------------
     470       ---Jump Back     Alt+-
     471       ---Jump Forward  Alt+Shift+-
     472       ------------------
   66225       ---Swi&tch File
     473       ---Next File     Ctrl+Pagedown
     474       ---Previous File Ctrl+Pageup
     475       ------------------
     476       ---Next File in Stack    Ctrl+Tab
     477       ---Previous File in Stack        Ctrl+Shift+Tab
     478       ------------------
     479       ---Switch &Header/Implementation Alt+O
     480       ------------------
     481       ---yuckeyt yuck ddddddddddddddddddddddddddddddddddddd    Alt+1
     482       ""
     483       ""
     484       ""
     485       ""
     486       ""
     487       ""
     488       ""
     489       ""
     490       ""
     491       ------------------
   66227       ---&Scroll
     492       ---Scroll to Selection   Ctrl+K, Ctrl+C
     493       ---Line Up       Ctrl+Up
     494       ---Line Down     Ctrl+Down
   66229       ---&Bookmarks
     495       ---Toggle Bookmark       Ctrl+F2
     496       ---Next Bookmark F2
     497       ---Prev Bookmark Shift+F2
     498       ---Clear Bookmarks       Ctrl+Shift+F2
     499       ---Select All Bookmarks  Alt+F2
     500       ------------------
     501       ---(No Bookmarks)
     502       ""
     503       ""
     504       ""
     505       ""
     506       ""
     507       ""
     508       ""
     509       ""
     510       ""
     511       ""
     512       ""
     513       ""
     514       ""
     515       ""
     516       ""
     517       ------------------
     518       ---Jump to Matching Bracket      Ctrl+M
   66231       ---&Tools
     519       ---Command Paletteà      Ctrl+Shift+P
     520       ---Snippetsà
     521       ------------------
   66233       ---B&uild System
     522   X   ---Automatic
     523       ------------------
     524       ""
     525       ""
     526       ""
     527       ""
     528       ""
     529       ""
     530       ""
     531       ""
     532       ""
     533       ""
     534       ""
     535       ""
     536       ""
     537       ---ActionScript
     538       ---Ant
     539       ---C Single File
     540       ---C++ Single File
     541       ---Cargo
     542       ---D
     543       ---D dub
     544       ---Erlang
     545       ---Haskell
     546       ---JavaC
     547       ---Lua
     548       ---Make
     549       ---Python
     550       ---R
     551       ---Ruby
     552       ---Rust
     553       ---ShellScript
     554       ---Syntax Tests
     555       ------------------
     556       ---New Build Systemà
     557       ---&Build        Ctrl+B
     558       ---Build Withà   Ctrl+Shift+B
     559       ---&Cancel Build Ctrl+Break
   66235       ---Build &Results
     560       ---&Show Build Results
     561       ---&Next Result  F4
     562       ---&Previous Result      Shift+F4
     563       ---Save &All on Build
     564       ------------------
     565       ---Record &Macro Ctrl+Q
     566       ---&Playback Macro       Ctrl+Shift+Q
     567       ---Sa&ve Macroà
   66237       ---Macros
     568       ---Add Line Before
     569       ---Add Line in Braces
     570       ---Add Line
     571       ---Delete Left Right
     572       ---Delete Line
     573       ---Delete to BOL
     574       ---Delete to EOL
     575       ---Delete to Hard BOL
     576       ---Delete to Hard EOL
     577       ------------------
   66239       ---Developer
     578       ---New Pluginà
     579       ---New Snippetà
     580       ---New Syntaxà
     581       ""
     582       ------------------
     583       ---Profile Plugins
     584       ------------------
     585       ---Show Scope Name       Ctrl+Alt+Shift+P
     586       ---Install Package Controlà
     587       ""
   66241       ---&Project
     588       ---Open Projectà
     589       ---Switch Projectà
     590       ---Quick &Switch Projectà
   66243       ---Open Recent
     591       ""
     592       ""
     593       ""
     594       ""
     595       ""
     596       ""
     597       ""
     598       ""
     599       ""
     600       ---Clear Items
     601       ------------------
     602       ---Save Project &Asà
     603       ---&Close Project
     604       ---Edit Project
     605       ------------------
     606       ---New Workspace for Project
     607       ---Save Workspace &Asà
     608       ------------------
     609       ---A&dd Folder to Projectà
     610       ---Re&move all Folders from Project
     611       ---R&efresh Folders
   66245       ---Prefere&nces
     612       ---&Browse Packagesà
     613       ------------------
     614       ---Settings
     615       ---Settings û Syntax Specific
     616       ---Settings û Distraction Free
     617       ------------------
     618       ---Key Bindings
     619       ------------------
     620       ---Color Schemeà
     621       ---Themeà
   66247       ---Font
     622       ---Larger        Ctrl+=
     623       ---Smaller       Ctrl+Shift+Keypad Plus
     624       ------------------
     625       ---Reset
   66249       ---&Help
     626       ---Documentation
     627       ---Twitter
     628       ------------------
     629       ---Indexing Statusà
     630       ------------------
     631       ---Purchase License
     632       ""
     633       ---Enter License
     634       ""
     635       ------------------
     636       ---Check for Updatesà
     637       ---Changelogà
     638       ---&About Sublime Text

是的,这当然是可行的。

您必须分析在执行某个 GUI 操作时究竟执行了哪些代码。这可能需要了解所使用的 GUI API。在 Qt 中伪造按钮按下与在标准 WinAPI 对话框中伪造按钮按下完全不同。

那将是解决它的更高层,了解该 GUI 操作的作用(WM_COMMAND例如,在 WinAPI 中发送消息,或在 Qt 中发出信号),然后执行该操作。

如果这对你来说太接近宏/伪造按键,你必须看看代码是如何做某事的。

一些虚构的 WinAPI 伪代码可能是:

if(msg == WM_COMMAND and button_id == BTN_ENABLE_STATUSBAR)
    show_statusbar();

所以如果你不想发送一个 fake WM_COMMAND,你可以注入直接调用 show_statusbar() 的代码。但是目标不必像那样整齐地包装它的代码。它可以只设置一些全局变量,然后重绘函数稍后会读取这些变量,看到状态栏标志被设置为可见,从而呈现状态栏。

这一切都归结为应用程序将 GUI 处理逻辑与应用程序逻辑分离的程度。最坏的情况是 GUI 处理代码包含所有应用程序逻辑代码。然后就很难只执行那个代码块了。

最好的情况是作为虚构示例,其中 GUI 逻辑仅调用另一个应用程序逻辑函数,因此您可以轻松地自己完成。