win_util.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 504 行

SVN-BASE
504
字号
/* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)   The author disclaims copyright to this source code. */#include "base_util.h"#include "win_util.h"#include "tstr_util.h"#ifdef _WIN32_WCE#include <aygshell.h>#include <Shlobj.h>#endif// Hmm, why have to redefine here (?!)#ifdef __GNUC__#define LVM_GETSELECTIONMARK     (LVM_FIRST+66)#define ListView_GetSelectionMark(w) (INT)SNDMSG((w),LVM_GETSELECTIONMARK,0,0)#endifint rect_dx(RECT *r){    int dx = r->right - r->left;    assert(dx >= 0);    return dx;}int rect_dy(RECT *r){    int dy = r->bottom - r->top;    assert(dy >= 0);    return dy;}void rect_set(RECT *r, int x, int y, int dx, int dy){    r->left = x;    r->top = y;    r->right = x + dx;    r->bottom = y + dy;}void win_set_font(HWND hwnd, HFONT font){    SendMessage(hwnd, WM_SETFONT, (WPARAM)font, 0);}int win_get_text_len(HWND hwnd){    return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);}void win_set_texta(HWND hwnd, const char *txt){    SendMessageA(hwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)txt);}void win_set_textw(HWND hwnd, const WCHAR *txt){    SendMessageW(hwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)txt);}/* return a text in edit control represented by hwnd   return NULL in case of error (couldn't allocate memory)   caller needs to free() the text */TCHAR *win_get_text(HWND hwnd){    int     cchTxtLen = win_get_text_len(hwnd);    TCHAR * txt = (TCHAR*)malloc((cchTxtLen+1)*sizeof(TCHAR));    if (NULL == txt)        return NULL;    SendMessage(hwnd, WM_GETTEXT, cchTxtLen + 1, (LPARAM)txt);    txt[cchTxtLen] = 0;    return txt;}void win_edit_set_selection(HWND hwnd, DWORD selStart, DWORD selEnd){   SendMessage(hwnd, EM_SETSEL, (WPARAM)selStart, (WPARAM)selEnd);}void win_edit_select_all(HWND hwnd){    win_edit_set_selection(hwnd, 0, -1);}LRESULT lv_delete_all_items(HWND hwnd){    return SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);}void lv_set_items_count(HWND hwnd, int items_count){    ListView_SetItemCount(hwnd, items_count);}int lv_get_items_count(HWND hwnd){    LRESULT count = ListView_GetItemCount(hwnd);    if (LB_ERR == count)        return 0;    return (int)count;}LRESULT lv_insert_column(HWND hwnd, int col, LVCOLUMN *lvc){    return SendMessage(hwnd, LVM_INSERTCOLUMN, col, (LPARAM)lvc);}LRESULT lv_set_column(HWND hwnd, int col, LVCOLUMN *lvc){    return SendMessage(hwnd, LVM_SETCOLUMN, col, (LPARAM)lvc);}LRESULT lv_set_column_dx(HWND hwnd, int col, int dx){    return ListView_SetColumnWidth(hwnd, col, dx);}LRESULT lv_insert_item(HWND hwnd, int row, LVITEM *lvi){    lvi->iItem = row;    lvi->iSubItem = 0;    return SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)lvi);}LRESULT lb_delete_string(HWND hwnd, int pos){    return SendMessage(hwnd, LB_DELETESTRING, pos, 0);}LRESULT lb_delete_all_items(HWND hwnd){#if 1    LRESULT    remaining_count;    for (;;) {        remaining_count = lb_delete_string(hwnd, 0);        if ((LB_ERR == remaining_count) || (0 == remaining_count))            break;    }    return 0;#else    LRESULT count;    int     i;    count = lb_get_items_count(hwnd);    if (LB_ERR == count)        return LB_ERR;    for (i=count-1; i--; i>=0) {        lb_delete_string(hwnd, i);    }    assert(0 == lb_get_items_count(hwnd);#endif}#if 0LRESULT lb_set_items_count(HWND hwnd, int items_count){    return SendMessage(hwnd, LB_SETCOUNT, items_count, 0);}#endifLRESULT lb_get_items_count(HWND hwnd){    return SendMessage(hwnd, LB_GETCOUNT, 0, 0);}LRESULT lb_insert_item_text(HWND hwnd, int row, const TCHAR *txt){    return SendMessage(hwnd, LB_INSERTSTRING, (WPARAM)row, (LPARAM)txt);}LRESULT lb_insert_item_textw(HWND hwnd, int row, const WCHAR *txt){    return SendMessageW(hwnd, LB_INSERTSTRING, (WPARAM)row, (LPARAM)txt);}LRESULT lb_append_string_no_sort(HWND hwnd, const TCHAR *txt){    return lb_insert_item_text(hwnd, -1, txt);}LRESULT lb_append_stringw_no_sort(HWND hwnd, const WCHAR *txt){    return lb_insert_item_textw(hwnd, -1, txt);}/* lb_get_selection and lb_set_selection only work for single-selection listbox */LRESULT lb_get_selection(HWND hwnd){    return SendMessage(hwnd, LB_GETCURSEL, 0, 0);}LRESULT lb_set_selection(HWND hwnd, int item){    assert(item >= 0);    return SendMessage(hwnd, LB_SETCURSEL, (WPARAM)item, 0);}LRESULT lv_insert_item_text(HWND hwnd, int row, const TCHAR *txt){    LVITEM  lvi = {0};    assert(txt);    if (!txt)        return -1; /* means failure */    lvi.mask = LVIF_TEXT;    lvi.pszText = (LPTSTR)txt;    return lv_insert_item(hwnd, row, &lvi);}/* Returns a selected item or -1 if no selection.   Assumes that the list is single-sel */int lv_get_selection_pos(HWND hwnd){    int selection;    int selected_count = ListView_GetSelectedCount(hwnd);    assert(selected_count <= 1);    if (0 == selected_count)        return -1;    selection = ListView_GetSelectionMark(hwnd);    return selection;}int font_get_dy_from_dc(HDC hdc, HFONT font){    TEXTMETRIC  tm;    HFONT       font_prev;    int         font_dy;    font_prev = (HFONT)SelectObject(hdc, font);    GetTextMetrics(hdc, &tm);    font_dy = tm.tmAscent + tm.tmDescent;    SelectObject(hdc, font_prev);    return font_dy;}int font_get_dy(HWND hwnd, HFONT font){    HDC         hdc;    int         font_dy = 0;    hdc = GetDC(hwnd);    if (hdc)        font_dy = font_get_dy_from_dc(hdc, font);    ReleaseDC(hwnd, hdc);    return font_dy;}#ifdef _WIN32_WCE/* see http://pocketpcdn.com/articles/wordcompletion.html for details   edit boxes on pocket pc by default have spelling suggestion/completion.   Sometimes we want/need to disable that and this is a function to do it. */void sip_completion_disable(void){    SIPINFO     info;    SHSipInfo(SPI_GETSIPINFO, 0, &info, 0);    info.fdwFlags |= SIPF_DISABLECOMPLETION;    SHSipInfo(SPI_SETSIPINFO, 0, &info, 0);}void sip_completion_enable(void){    SIPINFO     info;    SHSipInfo(SPI_GETSIPINFO, 0, &info, 0);    info.fdwFlags &= ~SIPF_DISABLECOMPLETION;    SHSipInfo(SPI_SETSIPINFO, 0, &info, 0);}#endifvoid launch_url(const TCHAR *url){    SHELLEXECUTEINFO sei;    BOOL             res;    if (NULL == url)        return;    ZeroMemory(&sei, sizeof(sei));    sei.cbSize  = sizeof(sei);    sei.fMask   = SEE_MASK_FLAG_NO_UI;    sei.lpVerb  = TEXT("open");    sei.lpFile  = url;    sei.nShow   = SW_SHOWNORMAL;    res = ShellExecuteEx(&sei);    return;}/* On windows those are defined as:#define CSIDL_PROGRAMS           0x0002#define CSIDL_PERSONAL           0x0005#define CSIDL_APPDATA            0x001a see shlobj.h for more */#ifdef CSIDL_APPDATA/* this doesn't seem to be defined on sm 2002 */#define SPECIAL_FOLDER_PATH CSIDL_APPDATA#endif#ifdef CSIDL_PERSONAL/* this is defined on sm 2002 and goes to "\My Documents".   Not sure if I should use it */ #ifndef SPECIAL_FOLDER_PATH  #define SPECIAL_FOLDER_PATH CSIDL_PERSONAL #endif#endif/* see http://www.opennetcf.org/Forums/post.asp?method=TopicQuote&TOPIC_ID=95&FORUM_ID=12    for more possibilities   return false on failure, true if ok. Even if returns false, it'll return root ("\")   directory so that clients can ignore failures from this function*/TCHAR *get_app_data_folder_path(BOOL f_create){#ifdef SPECIAL_FOLDER_PATH    BOOL        f_ok;    TCHAR       path[MAX_PATH];    f_ok = SHGetSpecialFolderPath(NULL, path, SPECIAL_FOLDER_PATH, f_create);    if (f_ok)        return tstr_dup(path);    else        return tstr_dup(_T(""));#else    /* if all else fails, just use root ("\") directory */    return tstr_dup(_T(""));#endif}void screen_get_dx_dy(int *dx_out, int *dy_out){    if (dx_out)        *dx_out = GetSystemMetrics(SM_CXSCREEN);    if (dy_out)        *dy_out = GetSystemMetrics(SM_CYSCREEN);}int screen_get_dx(void){    return (int)GetSystemMetrics(SM_CXSCREEN);}int screen_get_dy(void){    return (int)GetSystemMetrics(SM_CYSCREEN);}int screen_get_menu_dy(void){    return GetSystemMetrics(SM_CYMENU);}int screen_get_caption_dy(void){    return GetSystemMetrics(SM_CYCAPTION);}/* Ensure that the rectangle is at least partially in the work area on a   monitor. The rectangle is shifted into the work area if necessary. */void rect_shift_to_work_area(RECT *rect){    MONITORINFO mi;    mi.cbSize = sizeof mi;    GetMonitorInfo(MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST), &mi);        if (rect->bottom <= mi.rcWork.top) {        /* Rectangle is too far above work area */        rect->bottom += mi.rcWork.top - rect->top;        rect->top = mi.rcWork.top;    } else if (rect->top >= mi.rcWork.bottom) {        /* Rectangle is too far below */        rect->top -= rect->bottom - mi.rcWork.bottom;        rect->bottom = mi.rcWork.bottom;    }        if (rect->right <= mi.rcWork.left) {        /* Too far left */        rect->right += mi.rcWork.left - rect->left;        rect->left = mi.rcWork.left;    } else if (rect->left >= mi.rcWork.right) {        /* Right */        rect->left -= rect->right - mi.rcWork.right;        rect->right = mi.rcWork.right;    }}/* given a string id 'strId' from resources, get the string in a dynamically   allocated string.   Returns the string or NULL if error.   Caller needs to free() the string.   TODO: string is limited to BUF_CCH_SIZE. Could do it better by dynamically   allocating more memory if needed */#define BUF_CCH_SIZE 256TCHAR *load_string_dup(int str_id){    TCHAR buf[BUF_CCH_SIZE] = {0};    LoadString(NULL, str_id, buf, BUF_CCH_SIZE);    if (0 == tstr_len(buf))    {        assert(0);        return NULL;    }    return tstr_dup(buf);}const TCHAR *load_string(int str_id){    int          res;    const TCHAR *str;     /* little-known hack: when lpBuffer is NULL, LoadString() returns       a pointer to a string, that can be cast to TCHAR * (LPCTSTR)       requires -n option to RC (resource compiler)       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdk40/html/cerefLoadString.asp */    res = LoadString(NULL, str_id, NULL, 0);    if (0 == res)        return NULL;    str = (const TCHAR*)res;    return str;}// A helper to set a string, null-terminated 'keyValue' for a given 'keyName'// in 'keyPath'/'keyClass'// if 'keyName' is NULL then we set the default value for 'keyPath'// Returns false if there was any error (can be ignored)int regkey_set_str(HKEY key_class, TCHAR *key_path, TCHAR *key_name, TCHAR *key_value){    HKEY    hkey    = NULL;    DWORD   size  = 0;    BOOL    f_ok;    if (ERROR_SUCCESS != RegCreateKeyEx(key_class, key_path, 0, NULL, 0, 0, NULL, &hkey, NULL))        return FALSE;    f_ok = TRUE;    size = (DWORD)(tstr_len(key_value)*sizeof(TCHAR));    if (ERROR_SUCCESS != RegSetValueEx(hkey, key_name, 0, REG_SZ, (LPBYTE)key_value, size))        f_ok = FALSE;    RegCloseKey(hkey);    return f_ok;}int regkey_set_dword(HKEY key_class, TCHAR *key_path, TCHAR *key_name, DWORD key_value){    HKEY    hkey    = NULL;    DWORD   size  = 0;    BOOL    f_ok;    if (ERROR_SUCCESS != RegCreateKeyEx(key_class, key_path, 0, NULL, 0, 0, NULL, &hkey, NULL))        return FALSE;    f_ok = TRUE;    size = sizeof(DWORD);    if (ERROR_SUCCESS != RegSetValueEx(hkey, key_name, 0, REG_DWORD, (LPBYTE)&key_value, size))        f_ok = FALSE;    RegCloseKey(hkey);    return f_ok;}static void rect_client_to_screen(RECT *r, HWND hwnd){    POINT   p1 = {r->left, r->top};    POINT   p2 = {r->right, r->bottom};    ClientToScreen(hwnd, &p1);    ClientToScreen(hwnd, &p2);    r->left = p1.x;    r->top = p1.y;    r->right = p2.x;    r->bottom = p2.y;}void paint_round_rect_around_hwnd(HDC hdc, HWND hwnd_edit_parent, HWND hwnd_edit, COLORREF col){    RECT    r;    HBRUSH  br;    HBRUSH  br_prev;    HPEN    pen;    HPEN    pen_prev;    GetClientRect(hwnd_edit, &r);    br = CreateSolidBrush(col);    if (!br) return;    pen = CreatePen(PS_SOLID, 1, col);    pen_prev = SelectObject(hdc, pen);    br_prev = SelectObject(hdc, br);    rect_client_to_screen(&r, hwnd_edit_parent);    /* TODO: the roundness value should probably be calculated from the dy of the rect */    /* TODO: total hack: I manually adjust rectangle to values that fit g_hwnd_edit, as       found by experimentation. My mapping of coordinates isn't right (I think I need       mapping from window to window but even then it wouldn't explain -3 for y axis */    RoundRect(hdc, r.left+4, r.top-3, r.right+12, r.bottom-3, 8, 8);    if (br_prev)        SelectObject(hdc, br_prev);    if (pen_prev)        SelectObject(hdc, pen_prev);    DeleteObject(pen);    DeleteObject(br);}

⌨️ 快捷键说明

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