/* "Spam Filter"-Plugin for Miranda IM Copyright 2003-2006 Heiko Herkenrath This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program ("SpamFilter-License.txt"); if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // -- Includes #include "common.h" // -- Defines #define PROP_FILEEDIT_ASSO_BTN _T("FileEditBrowse_AssociatedButton") // ----------------------------------------- /* BOOL ResizeWindow(HWND hWnd, int cx, int cy, BOOL bRepaint) { RECT rc; if (GetWindowRect(hWnd, &rc)) return SetWindowPos(hWnd, NULL, 0, 0, (rc.right-rc.left)+cx, (rc.bottom-rc.top)+cy, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE|(bRepaint?0:SWP_NOREDRAW)); else return FALSE; } */ int GetCtrlTextExtent(HWND hwndCtrl, const WCHAR* pszText, BOOL bAddAveChar) { HDC hDC; HFONT hFont; SIZE size; HGDIOBJ hOldObj; if (!hwndCtrl || !pszText) return 0; hFont = (HFONT)SendMessage(hwndCtrl, WM_GETFONT, 0, 0); hDC = GetDC(hwndCtrl); if (!hDC) return 0; // If non-system font used select it first if (hFont) hOldObj = SelectObject(hDC, hFont); else hOldObj = NULL; if (!GetTextExtentPoint32(hDC, pszText, lstrlen(pszText), &size)) size.cx = 0; if (hFont) SelectObject(hDC, hOldObj); ReleaseDC(hwndCtrl, hDC); if (bAddAveChar) { TEXTMETRIC tm; if (GetTextMetrics(hDC, &tm)) size.cx += tm.tmAveCharWidth; } return size.cx; } BOOL ShowDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bShow) { HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl); if (!hwndCtrl) return FALSE; // Avoid flickering if (bShow && IsWindowVisible(hwndCtrl)) return TRUE; return ShowWindow(hwndCtrl, (bShow ? SW_SHOW : SW_HIDE)); } BOOL EnableDlgItem(HWND hwndDlg, int iIDCtrl, BOOL bEnable) { HWND hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl); if (!hwndCtrl) return FALSE; // Avoid flickering if (IsWindowEnabled(hwndCtrl) == bEnable) return (bEnable == FALSE); return EnableWindow(hwndCtrl, bEnable); } /* BOOL SetDlgItemPrintf(HWND hwndDlg, int iIDCtrl, unsigned int cbArgMaxLen, ...) { HWND hwndCtrl; BOOL bReturn; int iMaxLen; TCHAR* pszFmt; TCHAR* pszOut; va_list arglist; hwndCtrl = GetDlgItem(hwndDlg, iIDCtrl); if (!hwndCtrl) return FALSE; // Prepare fmt buffer iMaxLen = GetWindowTextLength(hwndCtrl); pszFmt = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR)); if (!pszFmt) return FALSE; // Get fmt text if (GetWindowText(hwndCtrl, pszFmt, iMaxLen+1) == 0) { mir_free(pszFmt); return FALSE; } // Prepare out buffer if (cbArgMaxLen > 0) iMaxLen = iMaxLen + cbArgMaxLen; pszOut = (TCHAR*)mir_alloc((iMaxLen+1)*sizeof(TCHAR)); if (!pszOut) { mir_free(pszFmt); return FALSE; } // Generate out text va_start(arglist, cbArgMaxLen); mir_vsnprintf(pszOut, iMaxLen+1, pszFmt, arglist); va_end(arglist); mir_free(pszFmt); bReturn = SetWindowText(hwndCtrl, pszOut); mir_free(pszOut); return bReturn; } */ BOOL SetSpinCtrlRange(HWND hwndSpin, int iRangeMin, int iRangeMax, int iDefault, BOOL bForceDefault) { HWND hwndDlg, hwndEdit; int iIDEdit; int iOldValue, iNewValue; int iOldRangeMin, iOldRangeMax; BOOL bIsEnabled; hwndDlg = GetParent(hwndSpin); if (!hwndDlg) return FALSE; hwndEdit = (HWND)SendMessage(hwndSpin, UDM_GETBUDDY, 0 , 0); if (!hwndEdit || (GetParent(hwndEdit) != hwndDlg)) return FALSE; iIDEdit = GetDlgCtrlID(hwndEdit); iOldValue = (int)GetDlgItemInt(hwndDlg, iIDEdit, NULL, TRUE); //if (iRangeMin < UD_MINVAL) iRangeMin = UD_MINVAL; //if (iRangeMax > UD_MAXVAL) iRangeMax = UD_MAXVAL; // Get data if (iRangeMax < iRangeMin) iRangeMax = iRangeMin; bIsEnabled = (iRangeMin != iRangeMax); SendMessage(hwndSpin, UDM_GETRANGE32, (WPARAM)&iOldRangeMin, (LPARAM)&iOldRangeMax); // Set default if necessary if (bForceDefault || ((iOldValue==iOldRangeMax) && (iDefault > iOldRangeMax)) || ((iOldValue==iOldRangeMin) && (iDefault < iOldRangeMin)) || (bIsEnabled && !IsWindowEnabled(hwndSpin) && !IsWindowEnabled(hwndEdit)) ) iNewValue = iDefault; else iNewValue = iOldValue; if (iNewValue < iRangeMin) iNewValue = iRangeMin; if (iNewValue > iRangeMax) iNewValue = iRangeMax; // Set edit if (iNewValue != iOldValue) SetDlgItemInt(hwndDlg, iIDEdit, iNewValue, TRUE); // Set spin if ((iRangeMin != iOldRangeMin) || iRangeMax != iOldRangeMax) { WCHAR szRangeMin[MAX_INT_LENGTH]; WCHAR szRangeMax[MAX_INT_LENGTH]; mir_sntprintf(szRangeMin, ARRAYSIZE(szRangeMin), _T("%i"), iRangeMin); mir_sntprintf(szRangeMax, ARRAYSIZE(szRangeMax), _T("%i"), iRangeMax); SendMessage(hwndSpin, UDM_SETRANGE32, (WPARAM)iRangeMin, (LPARAM)iRangeMax); PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)max(lstrlen(szRangeMin), lstrlen(szRangeMax)), 0); } if (iNewValue != iOldValue) SendMessage(hwndSpin, UDM_SETPOS32, 0, (LPARAM)iNewValue); // Avoiding flicker if (IsWindowEnabled(hwndSpin) != bIsEnabled) EnableWindow(hwndSpin, bIsEnabled); if (IsWindowEnabled(hwndEdit) != bIsEnabled) EnableWindow(hwndEdit, bIsEnabled); return bIsEnabled; } LRESULT CALLBACK PathEditSubclassProc(HWND hwndEdit, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lResult = CallWindowProc((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_USERDATA), hwndEdit, uMsg, wParam, lParam); switch(uMsg) { case WM_NCCALCSIZE: { if ((BOOL)wParam == TRUE) { // Resizing the client rect of the edit control // and moving the button in the space. HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN); NCCALCSIZE_PARAMS* pnccsp = (NCCALCSIZE_PARAMS*)lParam; RECT rc; if (hwndButton) if (GetWindowRect(hwndButton, &rc)) { rc.right -= rc.left; rc.bottom = pnccsp->rgrc[0].bottom-pnccsp->rgrc[0].top; pnccsp->rgrc[0].right -= (rc.right+1); rc.left = pnccsp->rgrc[0].right+1; rc.top = pnccsp->rgrc[0].top; MoveWindow(hwndButton, rc.left, rc.top, rc.right, rc.bottom, TRUE); } } break; } case WM_NCHITTEST: { // When the mouse is hovering the button // HTTRANSPARENT needs to be returned // else no mouse messages will be sent to the button if (lResult == HTNOWHERE) { HWND hwndButton = (HWND)GetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN); RECT rc; POINT pt; if (hwndButton) if (GetWindowRect(hwndButton, &rc)) { POINTSTOPOINT(pt, lParam); if (PtInRect(&rc, pt)) lResult = HTTRANSPARENT; } } break; } case WM_DROPFILES: { HDROP hDrop = (HDROP)wParam; WCHAR szFileName[MAX_PATH]; DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName)); // Insert the text and Mark it SetWindowText(hwndEdit, szFileName); DragFinish(hDrop); // Set focus to file editbox (SetFocus is not allowed in Dialogs) if (GetParent(hwndEdit)) PostMessage(GetParent(hwndEdit), WM_NEXTDLGCTL, (WPARAM)hwndEdit, (LPARAM)TRUE); break; } case WM_DESTROY: // before the destroy { // Remove assoicated browse button RemoveProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN); break; } case WM_NCDESTROY: // after the destroy { // Uninit auto complete if (GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete")) CoUninitialize(); break; } case WM_CHAR: { // Only allow valid path chars to be entered if (PathGetCharType((WCHAR)wParam)&GCT_INVALID) return FALSE; else break; } } return lResult; } BOOL MakePathEditCtrl(HWND hwndEdit, HWND hwndButton) { if (!hwndEdit || !hwndButton) return FALSE; // Don't make a new mask if there is already one available if((WNDPROC)GetWindowLongPtr(hwndEdit, GWLP_WNDPROC) == PathEditSubclassProc) return FALSE; // Remember associated button control if (!SetProp(hwndEdit, PROP_FILEEDIT_ASSO_BTN, (HANDLE)hwndButton)) { ShowWindow(hwndButton, SW_HIDE); return FALSE; } // Ansi/OEM codepage converting #if !defined(UNICODE) // Allow later converting to OEM encoding for some functions (see docs) SetWindowLongPtr(hwndEdit, GWL_STYLE, ES_OEMCONVERT|GetWindowLongPtr(hwndEdit, GWL_STYLE)); #endif // Limit text PostMessage(hwndEdit, EM_SETLIMITTEXT, (WPARAM)MAX_PATH, 0); // Subclass SetWindowLongPtr(hwndEdit, GWLP_USERDATA, SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)PathEditSubclassProc)); // Init auto complete { HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND, DWORD); *(FARPROC*)&MySHAutoComplete = GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "SHAutoComplete"); if (MySHAutoComplete) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); MySHAutoComplete(hwndEdit, SHACF_FILESYSTEM|SHACF_FILESYS_ONLY|SHACF_USETAB); } else OutputDebugString(_T("Spam Filter: SHAutoComplete in SHLWAPI.DLL not available.\r\n")); } // Accept drag & drop DragAcceptFiles(hwndEdit, TRUE); { RECT rcEdit; RECT rcButton; if (GetClientRect(hwndEdit, &rcEdit)) if (GetClientRect(hwndButton, &rcButton)) { // Send WM_NCCALCSIZE message to edit control and resize it to fit button SetWindowPos(hwndEdit, NULL, 0, 0, (rcEdit.right-rcEdit.left), (rcButton.bottom-rcButton.top)+2*GetSystemMetrics(SM_CYBORDER), SWP_NOMOVE|SWP_NOZORDER|SWP_DRAWFRAME); } } return TRUE; }