static LRESULT OnPaint(HWND hwnd) { ClientRect rect(hwnd); DoubleBuffer buffer(hwnd, rect); HDC hdc = buffer.GetDC(); HBRUSH brushBg = CreateSolidBrush(COL_WINDOW_BG); HBRUSH brushWhite = GetStockBrush(WHITE_BRUSH); FillRect(hdc, &rect.ToRECT(), brushBg); PreviewBase *preview = (PreviewBase *)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (preview && preview->renderer) { int pageNo = GetScrollPos(hwnd, SB_VERT); RectD page = preview->renderer->GetPageRect(pageNo); if (!page.IsEmpty()) { rect.Inflate(-PREVIEW_MARGIN, -PREVIEW_MARGIN); float zoom = (float)min(rect.dx / page.dx, rect.dy / page.dy) - 0.001f; RectI onScreen = RectD(rect.x, rect.y, page.dx * zoom, page.dy * zoom).Round(); onScreen.Offset((rect.dx - onScreen.dx) / 2, (rect.dy - onScreen.dy) / 2); FillRect(hdc, &onScreen.ToRECT(), brushWhite); preview->renderer->Render(hdc, onScreen, pageNo, zoom); } } DeleteObject(brushBg); DeleteObject(brushWhite); PAINTSTRUCT ps; buffer.Flush(BeginPaint(hwnd, &ps)); EndPaint(hwnd, &ps); return 0; }
void CenterDialog(HWND hDlg, HWND hParent) { if (!hParent) hParent = GetParent(hDlg); RectI rcDialog = WindowRect(hDlg); rcDialog.Offset(-rcDialog.x, -rcDialog.y); RectI rcOwner = WindowRect(hParent ? hParent : GetDesktopWindow()); RectI rcRect = rcOwner; rcRect.Offset(-rcRect.x, -rcRect.y); // center dialog on its parent window rcDialog.Offset(rcOwner.x + (rcRect.x - rcDialog.x + rcRect.dx - rcDialog.dx) / 2, rcOwner.y + (rcRect.y - rcDialog.y + rcRect.dy - rcDialog.dy) / 2); // ensure that the dialog is fully visible on one monitor rcDialog = ShiftRectToWorkArea(rcDialog, true); SetWindowPos(hDlg, 0, rcDialog.x, rcDialog.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); }
/* 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. */ RectI ShiftRectToWorkArea(RectI rect, bool bFully) { RectI monitor = GetWorkAreaRect(rect); if (rect.y + rect.dy <= monitor.y || bFully && rect.y < monitor.y) /* Rectangle is too far above work area */ rect.Offset(0, monitor.y - rect.y); else if (rect.y >= monitor.y + monitor.dy || bFully && rect.y + rect.dy > monitor.y + monitor.dy) /* Rectangle is too far below */ rect.Offset(0, monitor.y - rect.y + monitor.dy - rect.dy); if (rect.x + rect.dx <= monitor.x || bFully && rect.x < monitor.x) /* Too far left */ rect.Offset(monitor.x - rect.x, 0); else if (rect.x >= monitor.x + monitor.dx || bFully && rect.x + rect.dx > monitor.x + monitor.dx) /* Too far right */ rect.Offset(monitor.x - rect.x + monitor.dx - rect.dx, 0); return rect; }
RenderedBitmap *ImagesEngine::RenderBitmap(int pageNo, float zoom, int rotation, RectD *pageRect, RenderTarget target, AbortCookie **cookie_out) { RectD pageRc = pageRect ? *pageRect : PageMediabox(pageNo); RectI screen = Transform(pageRc, pageNo, zoom, rotation).Round(); screen.Offset(-screen.x, -screen.y); HDC hDC = GetDC(NULL); HDC hDCMem = CreateCompatibleDC(hDC); HBITMAP hbmp = CreateCompatibleBitmap(hDC, screen.dx, screen.dy); DeleteObject(SelectObject(hDCMem, hbmp)); bool ok = RenderPage(hDCMem, screen, pageNo, zoom, rotation, pageRect, target, cookie_out); DeleteDC(hDCMem); ReleaseDC(NULL, hDC); if (!ok) { DeleteObject(hbmp); return NULL; } return new RenderedBitmap(hbmp, screen.Size()); }
bool DjVuEngineImpl::RenderPage(HDC hDC, RectI screenRect, int pageNo, float zoom, int rotation, RectD *pageRect, RenderTarget target, AbortCookie **cookie_out) { bool success = true; RectD mediabox = PageMediabox(pageNo); HRGN clip = CreateRectRgn(screenRect.x, screenRect.y, screenRect.x + screenRect.dx, screenRect.y + screenRect.dy); SelectClipRgn(hDC, clip); DjVuAbortCookie *cookie = NULL; if (cookie_out) *cookie_out = cookie = new DjVuAbortCookie(); // render in 1 MB bands, as otherwise GDI can run out of memory RectD rect = pageRect ? *pageRect : mediabox; int bandDy = (int)((1 << 20) / (rect.dy * zoom)); PointI pt = Transform(rect, pageNo, zoom, rotation).TL().Convert<int>(); for (int y = 0; y * bandDy < rect.dy; y++) { RectD pageBand(rect.x, y * bandDy, rect.dx, bandDy); pageBand = pageBand.Intersect(mediabox); RectI screenBand = Transform(pageBand, pageNo, zoom, rotation).Round(); screenBand.Offset(screenRect.x - pt.x, screenRect.y - pt.y); RenderedBitmap *bmp = RenderBitmap(pageNo, zoom, rotation, &pageBand, target, cookie_out); if (bmp && bmp->GetBitmap()) success = bmp->StretchDIBits(hDC, screenBand); else success = false; delete bmp; if (cookie && cookie->abort) { success = false; break; } } SelectClipRgn(hDC, NULL); return success; }
static RectI GetTileOnScreen(BaseEngine *engine, int pageNo, int rotation, float zoom, TilePosition tile, RectI pageOnScreen) { RectI bbox = GetTileRectDevice(engine, pageNo, rotation, zoom, tile); bbox.Offset(pageOnScreen.x, pageOnScreen.y); return bbox; }
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { NPP instance = (NPP)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (uiMsg == WM_PAINT) { InstanceData *data = (InstanceData *)instance->pdata; PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); HBRUSH brushBg = CreateSolidBrush(COL_WINDOW_BG); HFONT hFont = GetSimpleFont(hDC, L"MS Shell Dlg", 14); bool isRtL = IsLanguageRtL(gTranslationIdx); // set up double buffering RectI rcClient = ClientRect(hWnd); DoubleBuffer buffer(hWnd, rcClient); HDC hDCBuffer = buffer.GetDC(); // display message centered in the window RECT rectClient = rcClient.ToRECT(); FillRect(hDCBuffer, &rectClient, brushBg); hFont = (HFONT)SelectObject(hDCBuffer, hFont); SetTextColor(hDCBuffer, RGB(0, 0, 0)); SetBkMode(hDCBuffer, TRANSPARENT); DrawCenteredText(hDCBuffer, rcClient, data->message, isRtL); // draw a progress bar, if a download is in progress if (0 < data->progress && data->progress <= 1) { SIZE msgSize; RectI rcProgress = rcClient; HBRUSH brushProgress = CreateSolidBrush(RGB(0x80, 0x80, 0xff)); GetTextExtentPoint32(hDCBuffer, data->message, (int)str::Len(data->message), &msgSize); rcProgress.Inflate(-(rcProgress.dx - msgSize.cx) / 2, -(rcProgress.dy - msgSize.cy) / 2 + 2); rcProgress.Offset(0, msgSize.cy + 4 + 2); RECT rectProgress = rcProgress.ToRECT(); FillRect(hDCBuffer, &rectProgress, GetStockBrush(WHITE_BRUSH)); RectI rcProgressAll = rcProgress; rcProgress.dx = (int)(data->progress * rcProgress.dx); rectProgress = rcProgress.ToRECT(); FillRect(hDCBuffer, &rectProgress, brushProgress); DeleteObject(brushProgress); ScopedMem<WCHAR> currSize(FormatSizeSuccint(data->currSize)); if (0 == data->totalSize || data->currSize > data->totalSize) { // total size unknown or bogus => show just the current size DrawCenteredText(hDCBuffer, rcProgressAll, currSize, isRtL); } else { ScopedMem<WCHAR> totalSize(FormatSizeSuccint(data->totalSize)); ScopedMem<WCHAR> s(str::Format(_TR("%s of %s"), currSize, totalSize)); DrawCenteredText(hDCBuffer, rcProgressAll, s, isRtL); } } // draw the buffer on screen buffer.Flush(hDC); DeleteObject(SelectObject(hDCBuffer, hFont)); DeleteObject(brushBg); EndPaint(hWnd, &ps); HWND hChild = FindWindowEx(hWnd, NULL, NULL, NULL); if (hChild) InvalidateRect(hChild, NULL, FALSE); } else if (uiMsg == WM_SIZE) { HWND hChild = FindWindowEx(hWnd, NULL, NULL, NULL); if (hChild) { ClientRect rcClient(hWnd); MoveWindow(hChild, rcClient.x, rcClient.y, rcClient.dx, rcClient.dy, FALSE); } } else if (uiMsg == WM_COPYDATA) { COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam; if (cds && 0x4C5255 /* URL */ == cds->dwData) { plogf("sp: NPN_GetURL %s", cds->dwData, (const char *)cds->lpData); gNPNFuncs.geturl(instance, (const char *)cds->lpData, "_blank"); return TRUE; } } return DefWindowProc(hWnd, uiMsg, wParam, lParam); }
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { InstanceData *data = (InstanceData *)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (uiMsg == WM_PAINT) { PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); HBRUSH brushBg = CreateSolidBrush(COL_WINDOW_BG); HFONT hFont = GetSimpleFont(hDC, _T("MS Shell Dlg"), 14); // set up double buffering RectI rcClient = ClientRect(hWnd); DoubleBuffer buffer(hWnd, rcClient); HDC hDCBuffer = buffer.GetDC(); // display message centered in the window FillRect(hDCBuffer, &rcClient.ToRECT(), brushBg); hFont = (HFONT)SelectObject(hDCBuffer, hFont); SetTextColor(hDCBuffer, RGB(0, 0, 0)); SetBkMode(hDCBuffer, TRANSPARENT); DrawCenteredText(hDCBuffer, rcClient, data->message); // draw a progress bar, if a download is in progress if (0 < data->progress && data->progress <= 1) { SIZE msgSize; RectI rcProgress = rcClient; HBRUSH brushProgress = CreateSolidBrush(RGB(0x80, 0x80, 0xff)); GetTextExtentPoint32(hDCBuffer, data->message, (int)str::Len(data->message), &msgSize); rcProgress.Inflate(-(rcProgress.dx - msgSize.cx) / 2, -(rcProgress.dy - msgSize.cy) / 2 + 2); rcProgress.Offset(0, msgSize.cy + 4 + 2); FillRect(hDCBuffer, &rcProgress.ToRECT(), GetStockBrush(WHITE_BRUSH)); RectI rcProgressAll = rcProgress; rcProgress.dx = (int)(data->progress * rcProgress.dx); FillRect(hDCBuffer, &rcProgress.ToRECT(), brushProgress); DeleteObject(brushProgress); ScopedMem<TCHAR> currSize(FormatSizeSuccint(data->currSize)); if (0 == data->totalSize || data->currSize > data->totalSize) { // total size unknown or bogus => show just the current size DrawCenteredText(hDCBuffer, rcProgressAll, currSize); } else { ScopedMem<TCHAR> totalSize(FormatSizeSuccint(data->totalSize)); ScopedMem<TCHAR> s(str::Format(_T("%s of %s"), currSize, totalSize)); DrawCenteredText(hDCBuffer, rcProgressAll, s); } } // draw the buffer on screen buffer.Flush(hDC); DeleteObject(SelectObject(hDCBuffer, hFont)); DeleteObject(brushBg); EndPaint(hWnd, &ps); HWND hChild = FindWindowEx(hWnd, NULL, NULL, NULL); if (hChild) InvalidateRect(hChild, NULL, FALSE); } else if (uiMsg == WM_SIZE) { HWND hChild = FindWindowEx(hWnd, NULL, NULL, NULL); if (hChild) { ClientRect rcClient(hWnd); MoveWindow(hChild, rcClient.x, rcClient.y, rcClient.dx, rcClient.dy, FALSE); } } return DefWindowProc(hWnd, uiMsg, wParam, lParam); }