Wrap the newer icon extraction API

This commit is contained in:
Kovid Goyal 2023-01-04 20:07:05 +05:30
parent 8874ff73aa
commit 630c24407c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 39 additions and 4 deletions

View File

@ -173,7 +173,7 @@
"only": "windows", "only": "windows",
"headers": "calibre/utils/cpp_binding.h calibre/utils/windows/common.h", "headers": "calibre/utils/cpp_binding.h calibre/utils/windows/common.h",
"sources": "calibre/utils/windows/winutil.cpp", "sources": "calibre/utils/windows/winutil.cpp",
"libraries": "shell32 wininet advapi32", "libraries": "shell32 wininet advapi32 gdi32",
"cflags": "/X" "cflags": "/X"
}, },
{ {

View File

@ -149,7 +149,7 @@ image_from_hbitmap(void* hbitmap) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
return QImage::fromHBITMAP((HBITMAP)hbitmap); return QImage::fromHBITMAP((HBITMAP)hbitmap);
#else #else
(void)hibitmap; (void)hbitmap;
return QImage(); return QImage();
#endif #endif
} }

View File

@ -75,7 +75,7 @@ static PyMethodDef PyGUID_methods[] = {
// }}} // }}}
// Handle {{{ // Handle {{{
typedef enum { NormalHandle, ModuleHandle, IconHandle } WinHandleType; typedef enum { NormalHandle, ModuleHandle, IconHandle, BitmapHandle } WinHandleType;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
@ -94,6 +94,8 @@ Handle_close_(Handle *self) {
FreeLibrary((HMODULE)self->handle); break; FreeLibrary((HMODULE)self->handle); break;
case IconHandle: case IconHandle:
DestroyIcon((HICON)self->handle); break; DestroyIcon((HICON)self->handle); break;
case BitmapHandle:
DeleteObject((HBITMAP)self->handle); break;
} }
self->handle = NULL; self->handle = NULL;
} }
@ -132,6 +134,8 @@ Handle_repr(Handle * self) {
name = "HMODULE"; break; name = "HMODULE"; break;
case IconHandle: case IconHandle:
name = "HICON"; break; name = "HICON"; break;
case BitmapHandle:
name = "HBITMAP"; break;
} }
return PyUnicode_FromFormat("<Win32 handle of type %s at: %p %V>", name, self->handle, self->associated_name, ""); return PyUnicode_FromFormat("<Win32 handle of type %s at: %p %V>", name, self->handle, self->associated_name, "");
} }
@ -162,6 +166,7 @@ Handle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
case NormalHandle: case NormalHandle:
case IconHandle: case IconHandle:
case ModuleHandle: case ModuleHandle:
case BitmapHandle:
break; break;
default: default:
PyErr_Format(PyExc_TypeError, "unknown handle type: %d", type); PyErr_Format(PyExc_TypeError, "unknown handle type: %d", type);
@ -978,7 +983,7 @@ write_file(PyObject *self, PyObject *args) {
DWORD written = 0; DWORD written = 0;
BOOL ok; BOOL ok;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
ok = WriteFile(handle, data + offset, size - offset, &written, NULL); ok = WriteFile(handle, data + offset, (DWORD)(size - offset), &written, NULL);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (!ok) return set_error_from_handle(args); if (!ok) return set_error_from_handle(args);
return PyLong_FromUnsignedLong(written); return PyLong_FromUnsignedLong(written);
@ -1134,6 +1139,34 @@ get_icon_for_file(PyObject *self, PyObject *args) {
return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, ERROR_RESOURCE_TYPE_NOT_FOUND, PyTuple_GET_ITEM(args, 0)); return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, ERROR_RESOURCE_TYPE_NOT_FOUND, PyTuple_GET_ITEM(args, 0));
} // }}} } // }}}
static PyObject*
get_bitmap_for_file(PyObject *self, PyObject *args) {
wchar_raii path;
long width = 256, height = 256;
if (!PyArg_ParseTuple(args, "O&|ll", py_to_wchar_no_none, &path, &width, &height)) return NULL;
scoped_com_initializer com;
if (!com.succeeded()) { PyErr_SetString(PyExc_OSError, "Failed to initialize COM"); return NULL; }
IShellItemImageFactory *pImageFactory;
HRESULT hr;
Py_BEGIN_ALLOW_THREADS
hr = SHCreateItemFromParsingName(path.ptr(), NULL, IID_PPV_ARGS(&pImageFactory));
Py_END_ALLOW_THREADS
if (!SUCCEEDED(hr)) {
return error_from_hresult(hr, "Failed to create Shell Item from path");
}
SIZE size = { width, height };
HBITMAP hbmp;
Py_BEGIN_ALLOW_THREADS
hr = pImageFactory->GetImage(size, SIIGBF_BIGGERSIZEOK, &hbmp);
pImageFactory->Release();
Py_END_ALLOW_THREADS
if (!SUCCEEDED(hr)) {
return error_from_hresult(hr, "Failed to get image from shell item");
}
return (PyObject*)Handle_create(hbmp, BitmapHandle);
}
// Boilerplate {{{ // Boilerplate {{{
static const char winutil_doc[] = "Defines utility methods to interface with windows."; static const char winutil_doc[] = "Defines utility methods to interface with windows.";
@ -1156,6 +1189,7 @@ static PyMethodDef winutil_methods[] = {
M(load_library, METH_VARARGS), M(load_library, METH_VARARGS),
M(load_icons, METH_VARARGS), M(load_icons, METH_VARARGS),
M(get_icon_for_file, METH_VARARGS), M(get_icon_for_file, METH_VARARGS),
M(get_bitmap_for_file, METH_VARARGS),
M(parse_cmdline, METH_VARARGS), M(parse_cmdline, METH_VARARGS),
M(write_file, METH_VARARGS), M(write_file, METH_VARARGS),
M(wait_named_pipe, METH_VARARGS), M(wait_named_pipe, METH_VARARGS),
@ -1463,6 +1497,7 @@ exec_module(PyObject *m) {
A(NormalHandle); A(NormalHandle);
A(ModuleHandle); A(ModuleHandle);
A(IconHandle); A(IconHandle);
A(BitmapHandle);
A(KF_FLAG_DEFAULT); A(KF_FLAG_DEFAULT);
A(KF_FLAG_FORCE_APP_DATA_REDIRECTION); A(KF_FLAG_FORCE_APP_DATA_REDIRECTION);