|
4 | 4 | #include <flutter/plugin_registrar_windows.h>
|
5 | 5 | #include <flutter/standard_method_codec.h>
|
6 | 6 |
|
| 7 | + |
7 | 8 | #include <Windows.h>
|
8 | 9 | #include <ShlObj.h>
|
| 10 | +#include <gdiplus.h> |
9 | 11 |
|
10 | 12 | #include <map>
|
11 | 13 | #include <memory>
|
12 | 14 |
|
13 | 15 | #include "strconv.h"
|
14 | 16 |
|
| 17 | +#pragma comment(lib, "GdiPlus") |
| 18 | + |
15 | 19 | namespace {
|
16 | 20 |
|
17 | 21 | constexpr STGMEDIUM kNullStorageMedium = {TYMED_NULL, nullptr, nullptr};
|
@@ -131,6 +135,49 @@ PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp) {
|
131 | 135 | return pbmi;
|
132 | 136 | }
|
133 | 137 |
|
| 138 | +// The code was taken from this answer: https://stackoverflow.com/a/39201008/2134488 |
| 139 | +// |
| 140 | +bool CopyImageToClipboard(const wchar_t* filename) |
| 141 | +{ |
| 142 | + //initialize Gdiplus once: |
| 143 | + Gdiplus::GdiplusStartupInput gdiplusStartupInput; |
| 144 | + ULONG_PTR gdiplusToken; |
| 145 | + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); |
| 146 | + |
| 147 | + bool result = false; |
| 148 | + Gdiplus::Bitmap *gdibmp = Gdiplus::Bitmap::FromFile(filename); |
| 149 | + if (gdibmp) |
| 150 | + { |
| 151 | + HBITMAP hbitmap; |
| 152 | + gdibmp->GetHBITMAP(0, &hbitmap); |
| 153 | + if (OpenClipboard(NULL)) |
| 154 | + { |
| 155 | + EmptyClipboard(); |
| 156 | + DIBSECTION ds; |
| 157 | + if (GetObject(hbitmap, sizeof(DIBSECTION), &ds)) |
| 158 | + { |
| 159 | + HDC hdc = GetDC(HWND_DESKTOP); |
| 160 | + //create compatible bitmap (get DDB from DIB) |
| 161 | + HBITMAP hbitmap_ddb = CreateDIBitmap(hdc, &ds.dsBmih, CBM_INIT, |
| 162 | + ds.dsBm.bmBits, (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS); |
| 163 | + ReleaseDC(HWND_DESKTOP, hdc); |
| 164 | + SetClipboardData(CF_BITMAP, hbitmap_ddb); |
| 165 | + DeleteObject(hbitmap_ddb); |
| 166 | + result = true; |
| 167 | + } |
| 168 | + CloseClipboard(); |
| 169 | + } |
| 170 | + |
| 171 | + //cleanup: |
| 172 | + DeleteObject(hbitmap); |
| 173 | + delete gdibmp; |
| 174 | + } |
| 175 | + |
| 176 | + Gdiplus::GdiplusShutdown(gdiplusToken); |
| 177 | + |
| 178 | + return result; |
| 179 | +} |
| 180 | + |
134 | 181 | void CreateBMPFile(LPCTSTR pszFile, HBITMAP hBMP) {
|
135 | 182 | HANDLE hf; // file handle
|
136 | 183 | BITMAPFILEHEADER hdr; // bitmap file-header
|
@@ -431,6 +478,34 @@ void PasteboardPlugin::HandleMethodCall(
|
431 | 478 | SetClipboardData(CF_HDROP, storage.hGlobal);
|
432 | 479 | result->Success();
|
433 | 480 | }
|
| 481 | + else if (method_call.method_name() == "writeImage") { |
| 482 | + |
| 483 | + |
| 484 | + const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments()); |
| 485 | + |
| 486 | + std::string fileName; |
| 487 | + if (arguments) { |
| 488 | + auto it = arguments->find(flutter::EncodableValue("fileName")); |
| 489 | + if (it != arguments->end()) { |
| 490 | + if (std::holds_alternative<std::string>(it->second)) { |
| 491 | + fileName = std::get<std::string>(it->second); |
| 492 | + } |
| 493 | + } |
| 494 | + } |
| 495 | + |
| 496 | + if (fileName.size() == 0) { |
| 497 | + result->Error("0", "File name is empty"); |
| 498 | + return; |
| 499 | + } |
| 500 | + std::wstring wsFileName = cp_to_wide(fileName, CP_UTF8); |
| 501 | + |
| 502 | + if (!CopyImageToClipboard(wsFileName.c_str())) { |
| 503 | + result->Error("0", "Failed to copy image to clipboard"); |
| 504 | + return; |
| 505 | + } |
| 506 | + |
| 507 | + result->Success(); |
| 508 | +} |
434 | 509 | else if (method_call.method_name() == "html") {
|
435 | 510 |
|
436 | 511 | UINT CF_HTML = RegisterClipboardFormatA("HTML Format");
|
|
0 commit comments