如何在电脑桌面放一个固定的计算表格? 您所在的位置:网站首页 todo如何放在桌面 如何在电脑桌面放一个固定的计算表格?

如何在电脑桌面放一个固定的计算表格?

#如何在电脑桌面放一个固定的计算表格?| 来源: 网络整理| 查看: 265

https://www.zhihu.com/video/1622575424101421056

正好无聊看到这个问题,觉着挺有意思,花了点时间尝试了一下。

由于你要支持公式,所以干脆直接引入lua,就不用麻烦的解析字符串了。

定义结构 Cell定义结构 Sheet设置lua globaltable元方法__index,__newindex创建窗口,创建EDITEDIT得到焦点后,显示Formula公式EDIT丢失焦点后,显示Value,计算后的值

从上述的内容来看,代码大概如下

struct Cell { HWND hWnd; //对应Edit的窗口句柄 std::string Formula; //公式 std::string Value; //计算后的值 std::string Name; //在lua中对应的变量名称 };

Cell结构中的Name,是对应在lua中的变量名称

例如,第一行第一列单元格的变量名称就为A1

第一行第二列单元格的变量名称就为B1

之后定义总的行列数量

#define ROW_COUNT 5 #define COLUMN_COUNT 5

定义行高,列宽

#define ROW_HEIGHT 30 #define COLUMN_WIDTH 100

定义Sheet结构

struct Sheet { Cell cells[ROW_COUNT][COLUMN_COUNT]; static int __index(lua_State* L); static int __newindex(lua_State* L); }

该结构中的两个静态函数,分别对应lua全局表中的元方法__index,__newindex

在main函数中设置全局表的元方法

#include lua_State* _state; int main() { _state = luaL_newstate(); Sheet* pSheet = new Sheet; luaL_openlibs(_state ); lua_pushglobaltable(_state ); lua_newtable(_state ); lua_pushstring(_state , "__index"); lua_pushlightuserdata(_state , pSheet); lua_pushcclosure(_state , &Sheet::__index, 1); lua_rawset(_state , -3); lua_pushstring(_state , "__newindex"); lua_pushlightuserdata(_state , pSheet); lua_pushcclosure(_state , &Sheet::__newindex, 1); lua_rawset(_state , -3); lua_setmetatable(_state , -2); lua_pop(_state,1); ...... }

设置元方法后,由于没有设置A1...AA1等变量的内容,所以在执行A1=111,A2=222等脚本代码的时候会调用__newindex函数,调用该函数的参数为 __newindex(t,k,v)

k 就等于 "A1" 字符串

v 就等于待设置的内容

同样的,在A2单元格输入公式 =A1,那么会先用A1作为key调用__index(t,key),然后会用返回的值v来调用__newindex(t,"A2",v)

调用过程大致就是这样,接下来创建窗口

#define TOTAL_HEIGHT ROW_HEIGHT * ROW_COUNT #define TOTAL_WIDTH COLUMN_WIDTH*COLUMN_COUNT HWND hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,_T("DesktopSheet"), _T("DesktopSheet"), WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, TOTAL_WIDTH, TOTAL_HEIGHT, nullptr, nullptr, hInstance, nullptr); // 创建Edit HWND lastWindow = HWND_TOP; for(int r = 0; r < ROW_COUNT;r++) { for(int c = 0; c < COLUMN_COUNT;c++) { pSheet->cells[r][c].hWnd = CreateWindow(_T("Edit"), _T(""), WS_CHILD| WS_TABSTOP | WS_VISIBLE|WS_BORDER|ES_WANTRETURN| ES_AUTOHSCROLL, c * COLUMN_WIDTH, r * ROW_HEIGHT, COLUMN_WIDTH, ROW_HEIGHT, hWnd, (HMENU)(ID_EDIT_FIRST + r * COLUMN_COUNT + c), hInstance, nullptr); int column_name = c+1; do { int x = column_name % 26; if (x == 0)x = 26; pSheet->cells[r][c].Name += (char)(x + 64); column_name = (column_name - x) / 26; } while (column_name > 0); std::reverse(pSheet->cells[r][c].Name.begin(), pSheet->cells[r][c].Name.end()); pSheet->cells[r][c].Name += std::format("{}", r + 1); ::SetWindowLongPtr(pSheet->cells[r][c].hWnd, GWLP_USERDATA, reinterpret_cast(&pSheet->cells[r][c])); SetWindowPos(pSheet->cells[r][c].hWnd, lastWindow, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); lastWindow = pSheet->cells[r][c].hWnd; } } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_TAB || msg.wParam == VK_RETURN) { HWND hwndx = GetFocus(); if (msg.wParam == VK_RETURN) { for (int i = 0; i < COLUMN_COUNT; i++) hwndx = GetNextWindow(hwndx, GW_HWNDNEXT); } else hwndx = GetNextWindow(hwndx, GW_HWNDNEXT); SetFocus(hwndx); } } TranslateMessage(&msg); DispatchMessage(&msg); } lua_close(_lState); delete pSheet;

窗口过程

LRESULT __stdcall WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { cast WM_COMMAND: { HWND hWndChild = (HWND)lParam; WORD nEventId = HIWORD(wParam); if (nEventId == EN_SETFOCUS) { // Edit得到焦点,设置显示内容为公式 if (Cell* pCell = reinterpret_cast(static_cast(::GetWindowLongPtr(hWndChild, GWLP_USERDATA)))) { SetWindowTextA(hWndChild, pCell->Formula.c_str()); } } else if (nEventId == EN_KILLFOCUS) { //Edit丢失焦点,设置显示内容为计算结果 if (Cell* pCell = reinterpret_cast(static_cast(::GetWindowLongPtr(hWndChild, GWLP_USERDATA)))) { int len = GetWindowTextLengthA(hWndChild) + 1; char* text = new char[len + 1]; ZeroMemory(text, len + 1); GetWindowTextA(hWndChild, text, len); pCell->Formula = text; std::string strScript = pCell->Name; if (text[0] != '=') { pCell->Value = text; SetWindowTextA(hWndChild, pCell->Value.c_str()); } else { strScript += text; if (LUA_OK == luaL_dostring(_lState, strScript.c_str())) SetWindowTextA(hWndChild, pCell->Value.c_str()); } delete[] text; text = nullptr; } } break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }

由于引入了lua,所以你想怎么自定义就怎么自定义,你想搞什么公式就搞什么公式。

只需要在文件夹中创建lua脚本,在窗口过程中判断输入的内容是否为公式,如果是公式就检查函数是否已经存在,如果不存在,就在指定的文件夹中查找同名脚本文件,直接dofile就好。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有