/* device context data types Created July 1994, Mark Hammond (MHammond@cmutual.com.au) These are implemented using CDC's, and hDC's in the map Note that this source file contains embedded documentation. This documentation consists of marked up text inside the C comments, and is prefixed with an '@' symbol. The source files are processed by a tool called "autoduck" which generates Windows .hlp files. @doc */ #define PY_SSIZE_T_CLEAN // this module is Py_ssize_t clean! #include "stdafx.h" #include #include "win32dc.h" #include "win32gdi.h" #include "win32brush.h" #include "win32font.h" #include "win32pen.h" #include "win32bitmap.h" #include "win32rgn.h" // LOGPALETTE support. BOOL PyObject_AsLOGPALETTE(PyObject *obLogPal, LOGPALETTE **ppLogPal) { BOOL ok = FALSE; if (!PySequence_Check(obLogPal)) { PyErr_SetString(PyExc_TypeError, "LOGPALETTE must be a sequence"); return FALSE; } Py_ssize_t n = PySequence_Length(obLogPal); *ppLogPal = (LOGPALETTE *)malloc(sizeof(LOGPALETTE) + n * sizeof(PALETTEENTRY)); LOGPALETTE *pPal = *ppLogPal; if (pPal==NULL) { PyErr_SetString(PyExc_MemoryError, "Allocating LOGPALETTE"); return FALSE; } pPal->palVersion = 0x300; pPal->palNumEntries = PyWin_SAFE_DOWNCAST(n, Py_ssize_t, WORD); for (Py_ssize_t i=0;ipalPalEntry[i].peRed, &pPal->palPalEntry[i].peGreen, &pPal->palPalEntry[i].peBlue, &pPal->palPalEntry[i].peFlags)) { Py_XDECREF(subOb); goto done; } Py_XDECREF(subOb); } ok = TRUE; done: if (!ok) { free(pPal); } return ok; } void PyObject_FreeLOGPALETTE(LOGPALETTE *pLogPal) { if (pLogPal) free(pLogPal); } PyObject *PyObject_FromLOGPALETTE( LOGPALETTE *pLP) { PyObject *entries = PyTuple_New(pLP->palNumEntries); for (int i=0;ipalNumEntries;i++) { PyTuple_SET_ITEM(entries, i, Py_BuildValue("bbbb", pLP->palPalEntry[i].peRed, pLP->palPalEntry[i].peGreen, pLP->palPalEntry[i].peBlue, pLP->palPalEntry[i].peFlags)); } PyObject *rc = Py_BuildValue("lO", pLP->palVersion, entries); Py_DECREF(entries); return rc; } // @pymethod int|win32ui|CreatePalette|Creates a HPALETTE PyObject *win32uiCreatePalette(PyObject *self, PyObject *args) { // @pyparm |lp||The entries for the palette. PyObject *obLP; if (!PyArg_ParseTuple(args, "O", &obLP)) return NULL; LOGPALETTE *pLP; if (!PyObject_AsLOGPALETTE(obLP, &pLP)) return NULL; HPALETTE hp = CreatePalette(pLP); PyObject_FreeLOGPALETTE(pLP); if (hp==NULL) RETURN_API_ERR("CreatePalette"); return PyWinLong_FromHANDLE(hp); } // this returns a pointer that should not be stored. CDC *ui_dc_object::GetDC(PyObject *self) { return (CDC *)GetGoodCppObject( self, &type); } void ui_dc_object::SetAssocInvalid() { return; // do nothing. Dont call base as dont want my handle wiped. } ui_dc_object::~ui_dc_object() { if (m_deleteDC) { CDC *pDC = GetDC(this); if (pDC) ::DeleteDC (pDC->m_hDC); } } // @pymethod |win32ui|CreateDC|Creates an uninitialised device context. PyObject *ui_dc_object::create_dc( PyObject *self, PyObject *args ) { CHECK_NO_ARGS2(args, CreateDC); // create Python device context CDC *pDC = new CDC; ui_dc_object *dc = (ui_dc_object *) ui_assoc_object::make (ui_dc_object::type, pDC, true)->GetGoodRet(); if (dc) dc->bManualDelete= true; return dc; } // @pymethod |win32ui|CreateDCFromHandle|Creates a DC object from an integer handle. PyObject *ui_create_dc_from_handle (PyObject *self, PyObject *args) { HDC hDC; if (!PyArg_ParseTuple(args,"O&:CreateDCFromHandle", PyWinObject_AsHANDLE, &hDC)) return NULL; CDC* pDC = CDC::FromHandle(hDC); if (pDC==NULL) RETURN_ERR ("Could not create DC."); // create Python device context ui_dc_object *dc = (ui_dc_object *) ui_assoc_object::make (ui_dc_object::type, pDC)->GetGoodRet(); return dc; } // @pymethod |PyCDC|BitBlt|Copies a bitmap from the source device context to this device context. static PyObject * ui_dc_bitblt (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y, width, height, xsrc, ysrc; DWORD rop; PyObject *dc_ob; if (!PyArg_ParseTuple (args, "(ii)(ii)O(ii)i", &x, &y, // @pyparm (x,y)-ints|destPos||The logical x,y coordinates of the upper-left corner of the destination rectangle. &width, &height, // @pyparm (width, height)-ints|size||Specifies the width and height (in logical units) of the destination rectangle and source bitmap. &dc_ob, // @pyparm |dc||Specifies the PyCDC object from which the bitmap will be copied. It must be None if rop specifies a raster operation that does not include a source. &xsrc, &ysrc, // @pyparm (xSrc, ySrc)-ints|srcPos||Specifies the logical x,y coordinates of the upper-left corner of the source bitmap. &rop)) // @pyparm int|rop||Specifies the raster operation to be performed. See the win32 api documentation for details. return NULL; if (!ui_base_class::is_uiobject (dc_ob, &ui_dc_object::type)) RETURN_TYPE_ERR("The 'O' param must be a PyCDC object"); CDC *pSrcDC = NULL; if (dc_ob!=Py_None) { pSrcDC = ui_dc_object::GetDC(dc_ob); if (!pSrcDC) RETURN_ERR("The source DC is invalid"); } GUI_BGN_SAVE; BOOL ok = pDC->BitBlt(x, y, width, height, pSrcDC, xsrc, ysrc, rop); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|BitBlt RETURN_ERR("BitBlt failed"); RETURN_NONE; } // @pymethod |PyCDC|PatBlt|Creates a bit pattern on the device. static PyObject * ui_dc_patblt (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y, width, height; DWORD rop; if (!PyArg_ParseTuple (args, "(ii)(ii)i", &x, &y, // @pyparm (x,y)-ints|destPos||The logical x,y coordinates of the upper-left corner of the destination rectangle. &width, &height, // @pyparm (width, height)-ints|size||Specifies the width and height (in logical units) of the destination rectangle and source bitmap. &rop)) // @pyparm int|rop||Specifies the raster operation to be performed. See the win32 api documentation for details. return NULL; GUI_BGN_SAVE; BOOL ok = pDC->PatBlt(x, y, width, height, rop); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|BitBlt RETURN_ERR("PatBlt failed"); RETURN_NONE; } // @pymethod |PyCDC|SetPixel|Sets a pixel in a device context static PyObject * ui_dc_setpixel (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; long color, rcolor; if (!PyArg_ParseTuple (args, "iil", &x, // @pyparm int|x||Horizontal coordinate. &y, // @pyparm int|y||Vertical coordinate. &color)) { // @pyparm int|color||The brush color. return NULL; } GUI_BGN_SAVE; rcolor = pDC->SetPixel (x, y, color); GUI_END_SAVE; if (rcolor < 0) RETURN_ERR ("SetPixel failed"); return Py_BuildValue ("l", rcolor); } // @pymethod int|PyCDC|GetSafeHdc|Returns the HDC of this DC object. static PyObject * ui_dc_get_safe_hdc(PyObject *self, PyObject *args) { CHECK_NO_ARGS(args); CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; // @pyseemfc CDC|GetSafeHdc HDC hdc = pDC->GetSafeHdc(); return PyWinLong_FromHANDLE(hdc); } // @pymethod |PyCDC|GetPixel|Gets a pixel at a local in a device context static PyObject * ui_dc_get_pixel (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; long rcolor; if (!PyArg_ParseTuple (args, "ii", &x, // @pyparm int|x||Horizontal coordinate. &y)) { // @pyparm int|y||Vertical coordinate. return NULL; } GUI_BGN_SAVE; rcolor = pDC->GetPixel (x, y); GUI_END_SAVE; if (rcolor < 0) RETURN_ERR ("GetPixel failed"); return Py_BuildValue ("l", rcolor); } // @pymethod (x, y)|PyCDC|GetCurrentPosition|Retrieves the current position (in logical coordinates). static PyObject * ui_dc_get_current_position (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CHECK_NO_ARGS(args); CPoint pt; pt = pDC->GetCurrentPosition (); return Py_BuildValue ("(ii)", pt.x, pt.y); } // @pymethod |PyCDC|Pie|Draws a pie slice in a device context static PyObject * ui_dc_pie (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x1, y1, x2, y2, x3, y3, x4, y4; if (!PyArg_ParseTuple (args, "iiiiiiii", &x1, // @pyparm int|x1||X coordinate of upper left corner &y1, // @pyparm int|y1||Y coordinate of upper left corner &x2, // @pyparm int|x2||X coordinate of lower right corner &y2, // @pyparm int|y2||Y coordinate of lower right corner &x3, // @pyparm int|x3||X coordinate of starting point of arc &y3, // @pyparm int|y3||Y coordinate of starting point of arc &x4, // @pyparm int|x4||X coordinate of ending point of arc &y4)) { // @pyparm int|y4||Y coordinate of ending point of arc return NULL; } GUI_BGN_SAVE; int rc = pDC->Pie (x1, y1, x2, y2, x3, y3, x4, y4); GUI_END_SAVE; return Py_BuildValue ("i", rc); } // @pymethod |PyCDC|CreateCompatibleDC|Creates a memory device context that is compatible with this DC. PyObject *ui_dc_object::create_compatible_dc( PyObject *self, PyObject *args ) { // @comm Note that unlike the MFC version, this function // calls the global CreateCompatibleDC function and returns // a new object. PyObject *obDCFrom = Py_None; CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple(args, "|O:CreateCompatibleDC", &obDCFrom )) return NULL; // @pyparm |dcFrom|None|The source DC, or None to make a screen compatible DC. CDC *dcFrom = NULL; if (obDCFrom!=Py_None) dcFrom = GetDC(obDCFrom); HDC hDC = NULL; if (dcFrom) { hDC = dcFrom->GetSafeHdc(); } GUI_BGN_SAVE; HDC hcDC = ::CreateCompatibleDC(hDC); GUI_END_SAVE; if (!hcDC) // @pyseemfc CDC|CreateCompatibleDC RETURN_ERR("CreateCompatibleDC failed"); // create Python device context CDC *pcDC = pDC->FromHandle(hcDC); ui_dc_object *dc = (ui_dc_object *) ui_assoc_object::make (ui_dc_object::type, pcDC)->GetGoodRet(); return dc; } // @pymethod |PyCDC|CreatePrinterDC|Creates a device context for a specific printer PyObject *ui_dc_object::create_printer_dc( PyObject *self, PyObject *args ) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; TCHAR *printerName = NULL; PyObject *obprinterName=Py_None; if (!PyArg_ParseTuple(args, "|O:CreatePrinterDC", &obprinterName )) return NULL; // @pyparm string|printerName|None|The printer name, or None for the default printer if (!PyWinObject_AsTCHAR(obprinterName, &printerName, TRUE)) return NULL; BOOL result; if (printerName == NULL) { // Attempt to open the default printer CPrintInfo info; if (!AfxGetApp()->GetPrinterDeviceDefaults(&(info.m_pPD->m_pd))) { RETURN_ERR("No default printer found"); return NULL; } if (info.m_pPD->m_pd.hDC == NULL && !info.m_pPD->CreatePrinterDC()) { result = FALSE; } else { result = pDC->Attach(info.m_pPD->m_pd.hDC); info.m_pPD->m_pd.hDC = NULL; // Prevent this DC from being deleted } } else { // Attempt to open a specific printer HANDLE hPrinter; if (!::OpenPrinter(printerName, &hPrinter, NULL)) { PyWinObject_FreeTCHAR(printerName); RETURN_ERR("Unable to open printer"); return NULL; } PyWinObject_FreeTCHAR(printerName); DWORD len; unsigned char buf; ::GetPrinter(hPrinter, 2, &buf, 1, &len); unsigned char *buffer = new unsigned char[len]; result = ::GetPrinter(hPrinter, 2, buffer, len, &len); ::ClosePrinter(hPrinter); if (!result) { RETURN_ERR("Unable to get printer info"); delete [] buffer; return NULL; } PRINTER_INFO_2 *pinfo = (PRINTER_INFO_2*)buffer; GUI_BGN_SAVE; result = pDC->CreateDC(pinfo->pDriverName, pinfo->pPrinterName, NULL, NULL); // @pyseemfc CDC|CreateDC GUI_END_SAVE; delete [] buffer; } if (!result) RETURN_ERR("CreateDC failed"); RETURN_NONE; } // @pymethod |PyCDC|DeleteDC|Deletes all resources associated with a device context. static PyObject * ui_dc_delete_dc (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CHECK_NO_ARGS2(args, DeleteDC); GUI_BGN_SAVE; BOOL ok = pDC->DeleteDC(); GUI_END_SAVE; if (!ok) RETURN_ERR("DeleteDC failed"); RETURN_NONE; // @comm In general, do not call this function; the destructor will do it for you. // An application should not call DeleteDC if objects have been selected into the device context. Objects must first be selected out of the device context before it it is deleted. // An application must not delete a device context whose handle was obtained by calling CWnd::GetDC. Instead, it must call CWnd::ReleaseDC to free the device context. // The DeleteDC function is generally used to delete device contexts created with CreateDC, CreateIC, or CreateCompatibleDC. } // @pymethod |PyCDC|DrawIcon|Draws an icon on the DC. static PyObject * ui_dc_draw_icon (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; HICON hIcon; if (!PyArg_ParseTuple (args, "(ii)O&:DrawIcon", &x, &y, // @pyparm (x,y)|point||The point coordinate to draw to. PyWinObject_AsHANDLE, &hIcon)) // @pyparm |hIcon||The handle of the icon to draw. return NULL; GUI_BGN_SAVE; BOOL ok = pDC->DrawIcon (x,y, hIcon); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|DrawIcon RETURN_ERR ("DrawIcon failed"); else RETURN_NONE; } // @pymethod |PyCDC|DrawFocusRect|Draws a rectangle in the style used to // indicate the rectangle has focus static PyObject * ui_dc_draw_focus_rect (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); CRect rect; if (!pDC) { return NULL; // @pyparm (left, top, right, bottom)|rect||The coordinates of the // rectangle } else if (!PyArg_ParseTuple (args, "(iiii)", &rect.left, &rect.top, &rect.right, &rect.bottom)) { return NULL; } else { // it's a void function GUI_BGN_SAVE; pDC->DrawFocusRect (rect); // @pyseemfc CDC|DrawFocusRect GUI_END_SAVE; RETURN_NONE; } } //@pymethod |PyCDC|ExtTextOut|Writes text to the DC. static PyObject *ui_dc_ext_text_out (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; TCHAR *text; DWORD strLen; int x, y; UINT options; PyObject *obtext, *rectObject, *widthObject = NULL; RECT rect, *rectPtr; int *widths = NULL; if (!PyArg_ParseTuple (args, "iiiOO|O:ExtTextOut", &x, // @pyparm x|int||The x coordinate to write the text to. &y, // @pyparm y|int||The y coordinate to write the text to. &options, // @pyparm nOptions|int||Specifies the rectangle type. This parameter can be one, both, or neither of ETO_CLIPPED and ETO_OPAQUE &rectObject,// @pyparm (left, top, right, bottom)|rect||Specifies the text's bounding rectangle. (Can be None.) &obtext, // @pyparm text|string||The text to write. &widthObject)) // @pyparm (width1, width2, ...)|tuple||Optional array of values that indicate distance between origins of character cells. { return NULL; } // Parse out rectangle object if (rectObject != Py_None) { if (!PyArg_ParseTuple(rectObject, "iiii", &rect.left, &rect.top, &rect.right, &rect.bottom)) return NULL; rectPtr = ▭ } else rectPtr = NULL; if (!PyWinObject_AsTCHAR(obtext, &text, FALSE, &strLen)) return NULL; // Parse out widths if (widthObject) { BOOL error = !PyTuple_Check(widthObject); if (!error) { Py_ssize_t len = PyTuple_Size(widthObject); if (len == (strLen - 1)) { widths = new int[len + 1]; for (Py_ssize_t i = 0; i < len; i++) { PyObject *item = PyTuple_GetItem(widthObject, i); if (!PyInt_Check(item)) error = TRUE; else widths[i] = PyInt_AsLong(item); } } } if (error) { delete [] widths; PyWinObject_FreeTCHAR(text); RETURN_TYPE_ERR("The width param must be a tuple of integers with a length one less than that of the string"); } } GUI_BGN_SAVE; BOOL ret = pDC->ExtTextOut(x, y, options, rectPtr, text, strLen, widths); // @pyseemfc CDC|ExtTextOut GUI_END_SAVE; PyWinObject_FreeTCHAR(text); delete [] widths; if (!ret) { RETURN_API_ERR("CDC::TextOut"); } RETURN_NONE; // @rdesc Always none. If the function fails, an exception is raised. } // @pymethod int|PyCDC|RectVisible|Determines whether any part of the given rectangle lies within the clipping region of the display context. static PyObject *ui_dc_rect_visible( PyObject *self, PyObject *args ) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CRect rect; // @pyparm (left, top, right, bottom)|rect||The coordinates of the reactangle to be checked. if (!PyArg_ParseTuple(args,"(iiii):RectVisible", &rect.left, &rect.top, &rect.right, &rect.bottom)) return NULL; GUI_BGN_SAVE; int rc = pDC->RectVisible(&rect); GUI_END_SAVE; return Py_BuildValue("i",rc); // @pyseemfc CDC|RectVisible // @rdesc Non zero if any part of the rectangle lies within the clipping region, else zero. } // @pymethod |PyCDC|Arc|Draws an eliptical arc. static PyObject *ui_dc_arc (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CRect rect; POINT pts, pte; if (!PyArg_ParseTuple(args,"(iiii)(ii)(ii):Arc", // @pyparm (left, top, right, bottom)|rect||Specifies the ellipse's bounding rectangle &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (x,y)|pointStart||Specifies the x- and y-coordinates // of the point that defines the arc's starting point (in logical units). // This point does not have to lie exactly on the arc. &pts.x, &pts.y, // @pyparm (x,y)|pointEnd||Specifies the x- and y-coordinates // of the point that defines the arc's ending point (in logical units). // This point does not have to lie exactly on the arc. &pte.x, &pte.y )) return NULL; GUI_BGN_SAVE; BOOL ret = pDC->Arc(&rect, pts, pte); // @pyseemfc CDC|Arc GUI_END_SAVE; if (!ret) RETURN_API_ERR("CDC::Arc"); RETURN_NONE; // @rdesc Always none. If the function fails, an exception is raised. // @comm The arc drawn by using the function is a segment of the ellipse defined by the specified bounding rectangle. // The actual starting point of the arc is the point at which a ray drawn // from the center of the bounding rectangle through the specified starting // point intersects the ellipse. The actual ending point of the arc is the // point at which a ray drawn from the center of the bounding rectangle through // the specified ending point intersects the ellipse. The arc is drawn in a // counterclockwise direction. Since an arc is not a closed figure, it is // not filled. Both the width and height of the rectangle must be greater // than 2 units and less than 32,767 units. } // @pymethod |PyCDC|Chord|Draws a chord. static PyObject *ui_dc_chord (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CRect rect; POINT pts, pte; if (!PyArg_ParseTuple(args,"(iiii)(ii)(ii):Chord", // @pyparm (left, top, right, bottom)|rect||Specifies the ellipse's bounding rectangle &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (x,y)|pointStart||Specifies the x- and y-coordinates // of the point that defines the arc's starting point (in logical units). // This point does not have to lie exactly on the arc. &pts.x, &pts.y, // @pyparm (x,y)|pointEnd||Specifies the x- and y-coordinates // of the point that defines the arc's ending point (in logical units). // This point does not have to lie exactly on the arc. &pte.x, &pte.y )) return NULL; GUI_BGN_SAVE; BOOL ret = pDC->Chord(&rect,pts,pte); // @pyseemfc CDC|Chord GUI_END_SAVE; if (!ret) RETURN_API_ERR("CDC::Chord"); RETURN_NONE; // @rdesc Always none. If the function fails, an exception is raised. // @comm Draws a chord (a closed figure bounded by the intersection // of an ellipse and a line segment). The rect parameter specify the // upper-left and lower-right corners, respectively, of a rectangle // bounding the ellipse that is part of the chord. // The pointStart and pointEnd parameters specify // the endpoints of a line that intersects the ellipse. // The chord is drawn by using the selected pen and filled // by using the selected brush. } // @pymethod |PyCDC|Ellipse|Draws an Ellipse. static PyObject *ui_dc_ellipse (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CRect rect; // @pyparm (left, top, right, bottom)|rect||Specifies the ellipse's bounding rectangle if (!PyArg_ParseTuple(args,"(iiii):Ellipse", &rect.left, &rect.top, &rect.right, &rect.bottom)) return NULL; GUI_BGN_SAVE; BOOL ret = pDC->Ellipse(rect); // @pyseemfc CDC|Ellipse GUI_END_SAVE; if (!ret) RETURN_API_ERR("CDC::Ellipse"); RETURN_NONE; // @rdesc Always none. If the function fails, an exception is raised. // @comm The center of the ellipse is the center of the bounding rectangle // specified by rect. The ellipse is drawn with the current pen, and its // interior is filled with the current brush. } // @pymethod |PyCDC|Polygon|Draws an Polygon. static PyObject *ui_dc_polygon (PyObject *self, PyObject *args) { PyObject * point_list; CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple(args, "O:Polygon", &point_list)) { return NULL; } else if (!PyList_Check(point_list)) { return NULL; } else { // Convert the list of point tuples into an array of POINT structs Py_ssize_t num = PyList_Size (point_list); POINT * point_array = new POINT[num]; for (Py_ssize_t i=0; i < num; i++) { PyObject * point_tuple = PyList_GetItem (point_list, i); if (!PyTuple_Check (point_tuple) || PyTuple_Size (point_tuple) != 2) { PyErr_SetString (PyExc_ValueError, "point list must be a list of (x,y) tuples"); delete[] point_array; return NULL; } else { long x, y; PyObject *px, *py; px = PyTuple_GetItem (point_tuple, 0); py = PyTuple_GetItem (point_tuple, 1); if ((!PyInt_Check(px)) || (!PyInt_Check(py))) { PyErr_SetString (PyExc_ValueError, "point list must be a list of (x,y) tuples"); delete[] point_array; return NULL; } else { x = PyInt_AsLong (px); y = PyInt_AsLong (py); point_array[i].x = x; point_array[i].y = y; } } } // we have an array of POINT structs, now we // can finally draw the polygon. GUI_BGN_SAVE; BOOL ret = pDC->Polygon (point_array, PyWin_SAFE_DOWNCAST(num, Py_ssize_t, int)); GUI_END_SAVE; delete[] point_array; if (!ret) { RETURN_API_ERR("CDC::Polygon"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|PolyBezier|Draws one or more Bezier splines. static PyObject *ui_dc_poly_bezier (PyObject *self, PyObject *args) { PyObject * triple_list; int do_to=0; CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple(args, "O|i:PolyBezier[To]", &triple_list, &do_to)) { return NULL; } else if (!PyList_Check(triple_list)) { return NULL; } else { int index = 0; Py_ssize_t num = PyList_Size (triple_list); #define HURL \ do { \ PyErr_SetString (PyExc_ValueError, \ "arg must be a list of 3-tuples of (x,y) tuples"); \ delete[] point_array; \ return NULL; \ } \ while (0) POINT * point_array = new POINT[num*3]; for (Py_ssize_t i=0; i < num; i++) { PyObject * triplet = PyList_GetItem (triple_list, i); if (!PyTuple_Check (triplet) || PyTuple_Size (triplet) != 3) { HURL; } else { for (int j=0; j < 3; j++) { PyObject *point = PyTuple_GetItem (triplet, j); if (!PyTuple_Check (point) || PyTuple_Size (point) != 2) { HURL; } else { PyObject *px, *py; px = PyTuple_GetItem (point, 0); py = PyTuple_GetItem (point, 1); if (!PyInt_Check(px) || !PyInt_Check(py)) { HURL; } else { point_array[index].x = PyInt_AsLong (px); point_array[index].y = PyInt_AsLong (py); index++; } } } } } // we have an array of POINT structs, now we // can finally draw the splines.. BOOL result; if (do_to) { result = pDC->PolyBezierTo (point_array, index); } else { result = pDC->PolyBezier (point_array, index); } delete[] point_array; if (!result) { RETURN_API_ERR("CDC::PolyBezier[To]"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|FillRect|Fills a given rectangle with the specified brush static PyObject * ui_dc_fillrect (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; PyObject *obBrush; if (!PyArg_ParseTuple (args, "(iiii)O:FillRect", &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (left, top, right, bottom|rect||Specifies the bounding rectangle, in logical units. &obBrush)) // @pyparm |brush||Specifies the brush to use. return NULL; if (!ui_base_class::is_uiobject (obBrush, &PyCBrush::type)) RETURN_TYPE_ERR("The 'O' param must be a PyCBrush object"); CBrush *pBrush = PyCBrush::GetBrush(obBrush); if (!pBrush) return NULL; GUI_BGN_SAVE; pDC->FillRect( &rect, pBrush ); GUI_END_SAVE; // @pyseemfc CDC|FillRect RETURN_NONE; } // @pymethod |PyCDC|FillSolidRect|Fills the given rectangle with the specified solid color. static PyObject * ui_dc_fillsolidrect (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; int col; if (!PyArg_ParseTuple (args, "(iiii)i:FillSolidRect", &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (left, top, right, bottom|rect||Specifies the bounding rectangle, in logical units. &col)) // @pyparm int|color||Specifies the color to use. return NULL; GUI_BGN_SAVE; pDC->FillSolidRect( &rect, (COLORREF)col ); GUI_END_SAVE; // @pyseemfc CDC|FillSolidRect RETURN_NONE; } // @pymethod |PyCDC|FrameRect|Draws a border around the rectangle specified by rect static PyObject * ui_dc_framerect (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; PyObject *obBrush; if (!PyArg_ParseTuple (args, "(iiii)O:FrameRect", &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (left, top, right, bottom|rect||Specifies the bounding rectangle, in logical units. &obBrush)) // @pyparm |brush||Specifies the brush to use. return NULL; if (!ui_base_class::is_uiobject (obBrush, &PyCBrush::type)) RETURN_TYPE_ERR("The 'O' param must be a PyCBrush object"); CBrush *pBrush = PyCBrush::GetBrush(obBrush); if (!pBrush) RETURN_ERR("The PyCBrush parameter is invalid."); GUI_BGN_SAVE; pDC->FrameRect( &rect, pBrush ); GUI_END_SAVE; // @pyseemfc CDC|FrameRect RETURN_NONE; } // @pymethod |PyCDC|Draw3dRect|Draws a three-dimensional rectangle. static PyObject * ui_dc_draw3drect(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; int ctl, cbr; if (!PyArg_ParseTuple (args, "(iiii)ii:Draw3dRect", &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (left, top, right, bottom|rect||Specifies the bounding rectangle, in logical units. &ctl, // @pyparm int|colorTopLeft||Specifies the color of the top and left sides of the three-dimensional rectangle. &cbr)) // @pyparm int|colorBotRight||Specifies the color of the bottom and right sides of the three-dimensional rectangle. return NULL; GUI_BGN_SAVE; pDC->Draw3dRect( &rect, ctl, cbr); GUI_END_SAVE; // @pyseemfc CDC|Draw3dRect RETURN_NONE; } // @pymethod int|PyCDC|GetNearestColor|Returns the closest color a device can map. static PyObject *ui_dc_get_nearest_color (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int col; // @pyparm int|color||Specifies the color to be matched. if (!PyArg_ParseTuple (args, "i:GetNearestColor", &col)) return NULL; GUI_BGN_SAVE; int rc = pDC->GetNearestColor(col); GUI_END_SAVE; return Py_BuildValue ("i", rc); } // @pymethod (x,y)|PyCDC|GetTextExtentPoint|An alias for . // GetTextExtentPoint is the preferred win32api name, but GetTextExtent is the MFC name. // Calculates the width and height of a line of text using the current font to determine the dimensions. // @pyparm string|text||The text to calculate for. // @rdesc A tuple of integers with the size of the string, in logical units. // @pymethod (x,y)|PyCDC|GetTextExtent|Calculates the width and height of a line of text using the current font to determine the dimensions. static PyObject *ui_dc_get_text_extent (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; TCHAR *text; PyObject *obtext; DWORD strLen; // @pyparm string|text||The text to calculate for. if (!PyArg_ParseTuple (args, "O:GetTextExtent", &obtext)) return NULL; if (!PyWinObject_AsTCHAR(obtext, &text, FALSE, &strLen)) return NULL; GUI_BGN_SAVE; CSize sz = pDC->GetTextExtent(text, strLen); // @pyseemfc CFC|GetTextExtent GUI_END_SAVE; PyWinObject_FreeTCHAR(text); return Py_BuildValue ("(ii)", sz.cx, sz.cy); // @rdesc A tuple of integers with the size of the string, in logical units. } // @pymethod int|PyCDC|SetTextColor|Sets the text color to the specified color. static PyObject * ui_dc_set_text_color (PyObject *self, PyObject *args) { // @comm This text color is used when writing text to this device context and also when converting bitmaps between color and monochrome device contexts. // If the device cannot represent the specified color, the system sets the text color to the nearest physical color. // The background color for a character is specified by the SetBkColor and SetBkMode member functions. CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int new_color; // @pyparm int|color||A windows color specification. See the win32api documentation for details. if (!PyArg_ParseTuple (args, "i", &new_color)) return NULL; GUI_BGN_SAVE; int old_color = pDC->SetTextColor (new_color); // @pyseemfc CDC|SetTextColor GUI_END_SAVE; return Py_BuildValue ("i", old_color); // @rdesc The return value is the previous text color. } // @pymethod int|PyCDC|SetBkColor|Sets the current background color to the specified color. static PyObject * ui_dc_set_bk_color (PyObject *self, PyObject *args) { // @comm If the background mode is OPAQUE, the system uses the background color // to fill the gaps in styled lines, the gaps between hatched lines in brushes, and // the background in character cells. // The system also uses the background color when converting bitmaps between color and // monochrome device contexts. CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int new_color; if (!PyArg_ParseTuple (args, "i", &new_color)) // @pyparm int|color||A windows color specification. See the win32api documentation for details. return NULL; GUI_BGN_SAVE; int old_color = pDC->SetBkColor (new_color); // @pyseemfc CDC|SetBkColor GUI_END_SAVE; return Py_BuildValue ("i", old_color); // @rdesc The return value is the previous background color. } // @pymethod int|PyCDC|SetBkMode|Sets the current background mode to the specified mode. static PyObject * ui_dc_set_bk_mode (PyObject *self, PyObject *args) { // @comm Specifies the mode to be set. This parameter can be either OPAQUE or TRANSPARENT CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int new_mode; if (!PyArg_ParseTuple (args, "i", &new_mode)) // @pyparm int|mode||A background mode. May be either TRANSPARENT or OPAQUE. return NULL; GUI_BGN_SAVE; int old_mode = pDC->SetBkMode(new_mode); // @pyseemfc CDC|SetBkMode GUI_END_SAVE; return Py_BuildValue ("i", old_mode); // @rdesc The return value is the previous background mode. } // @pymethod (int, int)|PyCDC|SetBrushOrg|Specifies the origin that GDI will assign to the next brush that the application selects into the device context. static PyObject * ui_dc_set_brush_org (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; // @pyparm (x,y)|point||The new origin in device units. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; GUI_BGN_SAVE; CPoint pt = pDC->SetBrushOrg( x, y ); // @pyseemfc CDC|SetBrushOrg GUI_END_SAVE; return Py_BuildValue ("(ii)", pt.x, pt.y); // @rdesc The previous origin in device units. } // @pymethod (int,int)|PyCDC|GetBrushOrg|Retrieves the origin (in device units) of the brush currently selected for the device context. static PyObject * ui_dc_get_brush_org(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int item; if (!PyArg_ParseTuple (args, ":GetBrushOrg", &item)) return NULL; GUI_BGN_SAVE; CPoint pt = pDC->GetBrushOrg();// @pyseemfc CDC|GetBrushOrg GUI_END_SAVE; return Py_BuildValue ("ii", pt.x, pt.y); } // @pymethod int|PyCDC|GetDeviceCaps|Retrieves a capability of the device context. static PyObject * ui_dc_get_device_caps (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int item; if (!PyArg_ParseTuple (args, "i", &item)) // @pyparm int|index||The information requested. See the win32api documentation for details. return NULL; GUI_BGN_SAVE; int value = pDC->GetDeviceCaps (item); // @pyseemfc CDC|GetDeviceCaps GUI_END_SAVE; return Py_BuildValue ("i", value); // @rdesc The value of the requested capability } // @pymethod int|PyCDC|SetMapMode|Sets the mapping mode for the device context. static PyObject * ui_dc_set_map_mode (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int new_mode; if (!PyArg_ParseTuple (args, "i", &new_mode)) // @pyparm int|newMode||The new mode. Can be one of // MM_ANISOTROPIC, MM_HIENGLISH, MM_HIMETRIC, MM_ISOTROPIC, MM_LOENGLISH, MM_LOMETRIC, MM_TEXT, MM_TWIPS return NULL; GUI_BGN_SAVE; int old_mode = pDC->SetMapMode (new_mode); // @pyseemfc CDC|SetMapMode GUI_END_SAVE; if (old_mode == 0) RETURN_ERR ("SetMapMode failed"); else return Py_BuildValue ("i", old_mode); // @rdesc The previous mapping mode. } // @pymethod int|PyCDC|GetMapMode|Gets the mapping mode for the device context. static PyObject * ui_dc_get_map_mode (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, "")) return NULL; GUI_BGN_SAVE; int mode = pDC->GetMapMode (); // @pyseemfc CDC|GetMapMode GUI_END_SAVE; if (mode == 0) RETURN_ERR ("GetMapMode failed"); return PyInt_FromLong(mode); } // @pymethod x, y|PyCDC|SetWindowOrg|Sets the window origin of the device context static PyObject * ui_dc_set_window_org (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { int x, y; // @pyparm int, int|x,y||The new origin. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) { return NULL; } else { GUI_BGN_SAVE; CSize old_size = pDC->SetWindowOrg (x, y); GUI_END_SAVE; return Py_BuildValue ("(ii)", old_size.cx, old_size.cy); } } } // @pymethod x, y|PyCDC|GetWindowOrg|Retrieves the x- and y-coordinates of the origin of the window associated with the device context. static PyObject * ui_dc_get_window_org (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; CSize org = pDC->GetWindowOrg (); GUI_END_SAVE; return Py_BuildValue ("(ii)", org.cx, org.cy); } } } // @pymethod x, y|PyCDC|SetViewportOrg|Sets the viewport origin of the device context static PyObject * ui_dc_set_viewport_org (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { int x, y; // @pyparm int, int|x,y||The new origin. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) { return NULL; } else { GUI_BGN_SAVE; CSize old_size = pDC->SetViewportOrg (x, y); GUI_END_SAVE; return Py_BuildValue ("(ii)", old_size.cx, old_size.cy); } } } // @pymethod x, y|PyCDC|GetViewportOrg|Gets the viewport origin of the device context static PyObject * ui_dc_get_viewport_org (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; CSize org = pDC->GetViewportOrg (); GUI_END_SAVE; return Py_BuildValue ("(ii)", org.cx, org.cy); } } } // @pymethod x, y|PyCDC|GetViewportExt|Gets the viewport extent of the device context static PyObject * ui_dc_get_viewport_ext (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; CSize ext = pDC->GetViewportExt (); GUI_END_SAVE; return Py_BuildValue ("(ii)", ext.cx, ext.cy); } } } // @pymethod x, y|PyCDC|GetWindowExt|Gets the window extent of the device context static PyObject * ui_dc_get_window_ext (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; CSize ext = pDC->GetWindowExt (); GUI_END_SAVE; return Py_BuildValue ("(ii)", ext.cx, ext.cy); } } } // @pymethod int|PyCDC|SetGraphicsMode|Sets the graphics mode for the specified device context static PyObject * ui_dc_set_graphics_mode (PyObject * self, PyObject * args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { int mode; // @pyparm int|mode||The new mode. if (!PyArg_ParseTuple (args, "i", &mode)) { return NULL; } else { return Py_BuildValue ("i", SetGraphicsMode (pDC->GetSafeHdc(), mode)); } } } // @pymethod int|PyCDC|SetWorldTransform|sets a two-dimensional linear transformation between world space and page space for the specified device context. This transformation can be used to scale, rotate, shear, or translate graphics output. static PyObject * ui_dc_set_world_transform (PyObject * self, PyObject * args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { XFORM xf; if (!PyArg_ParseTuple (args, "ffffff", &xf.eM11, &xf.eM12, &xf.eM21, &xf.eM22, &xf.eDx, &xf.eDy )) { return NULL; } else { return Py_BuildValue ("i", SetWorldTransform (pDC->GetSafeHdc(), &xf)); } } } // @pymethod (x,y)|PyCDC|SetWindowExt|Sets the x,y extents of the window associated with the device context. static PyObject * ui_dc_set_window_ext (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; // @pyparm (x,y)|size||The new size. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; GUI_BGN_SAVE; CSize old_size = pDC->SetWindowExt (x, y); // @pyseemfc CDC|SetWindowExt GUI_END_SAVE; if (old_size.cx == 0 && old_size.cy == 0) RETURN_ERR ("SetWindowExt failed"); else return Py_BuildValue ("(ii)", old_size.cx, old_size.cy); // @rdesc The previous extents of the window (in logical units). } // @pymethod (x,y)|PyCDC|SetViewportExt|Sets the x,y extents of the viewport of the device context. static PyObject * ui_dc_set_viewport_ext (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y; // @pyparm (x,y)|size||The new size. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; GUI_BGN_SAVE; CSize old_size = pDC->SetViewportExt (x, y); // @pyseemfc CDC|SetViewportExt GUI_END_SAVE; if (old_size.cx == 0 && old_size.cy == 0) RETURN_ERR ("SetViewportExt failed"); else return Py_BuildValue ("(ii)", old_size.cx, old_size.cy); // @rdesc The previous extents of the viewport (in logical units). } // @pymethod int|PyCDC|SetTextAlign|Sets the text-alignment flags. static PyObject * ui_dc_set_text_align (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int new_flags; // @pyparm int|newFlags||The new alignment flags. Can be a combination of (TA_CENTER, TA_LEFT, TA_RIGHT), (TA_BASELINE, TA_BOTTOM, TA_TOP) and (TA_NOUPDATECP, TA_UPDATECP) // The default is TA_LEFT\|TA_TOP\|TA_NOUPDATECP if (!PyArg_ParseTuple (args, "i", &new_flags)) return NULL; GUI_BGN_SAVE; int old_flags = pDC->SetTextAlign (new_flags); // @pyseemfc CDC|SetTextAlign GUI_END_SAVE; return Py_BuildValue ("i", old_flags); // @rdesc The old alignment flags. } // @pymethod object|PyCDC|SelectObject|Selects an object into the device context. // Currently, only , , and objects are supported. static PyObject * ui_dc_select_object (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; PyObject *v; // @pyparm object|ob||The object to select. if (!PyArg_ParseTuple (args, "O", &v)) return NULL; if (ui_base_class::is_uiobject (v, &PyCFont::type)) { PyCFont *new_font = (PyCFont *) v; GUI_BGN_SAVE; CFont *cFont = pDC->SelectObject (new_font->GetFont()); GUI_END_SAVE; if (cFont == NULL) RETURN_ERR ("Select font object failed"); else { return ui_assoc_object::make (PyCFont::type, cFont); } } else if (ui_base_class::is_uiobject (v, &ui_bitmap::type)) { ui_bitmap *new_bitmap = (ui_bitmap *) v; GUI_BGN_SAVE; CBitmap *pbm = pDC->SelectObject (new_bitmap->GetBitmap()); GUI_END_SAVE; if (pbm == NULL) RETURN_ERR ("Select bitmap object failed"); else { return ui_assoc_object::make (ui_bitmap::type, pbm); } } else if (ui_base_class::is_uiobject (v, &PyCBrush::type)) { PyCBrush *new_brush = (PyCBrush *) v; GUI_BGN_SAVE; CBrush *pbm = pDC->SelectObject (PyCBrush::GetBrush(new_brush)); GUI_END_SAVE; if (pbm == NULL) RETURN_ERR ("Select brush object failed"); else { return ui_assoc_object::make (PyCBrush::type, pbm); } } else if (ui_base_class::is_uiobject (v, &ui_pen_object::type)) { ui_pen_object * new_pen = (ui_pen_object *) v; GUI_BGN_SAVE; CPen * cPen = pDC->SelectObject (new_pen->GetPen()); GUI_END_SAVE; if (cPen == NULL) { RETURN_ERR ("Select pen object failed"); } else { return ui_assoc_object::make (ui_pen_object::type, cPen); } } RETURN_ERR ("Attempt to select unsupported object type."); // @pyseemfc CDC|SelectObject // @rdesc The previously selected object. This will be the same type as the object parameter. } // @pymethod int|PyCDC|SelectPalette|Sets the logical palette. static PyObject * ui_dc_select_palette (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; HPALETTE hPal; BOOL bForceBG = FALSE; // @pyparm int|hPalette||The handle to the palette // @pyparm int|forceBackground||Specifies whether the logical palette is forced to be a background palette. if (!PyArg_ParseTuple (args, "i|i:SelectPalette", &hPal, &bForceBG)) return NULL; GUI_BGN_SAVE; HPALETTE ret = ::SelectPalette(pDC->GetSafeHdc(), hPal, bForceBG); // @pyseemfc CDC|SelectePalette GUI_END_SAVE; return PyWinLong_FromHANDLE(ret); // @rdesc The previous palette handle. } // @pymethod int|PyCDC|RealizePalette|Maps palette entries in the current logical palette to the system palette. static PyObject * ui_dc_realize_palette (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CHECK_NO_ARGS2(args, RealizePalette); GUI_BGN_SAVE; UINT ret = pDC->RealizePalette(); GUI_END_SAVE; return Py_BuildValue ("i", ret); // @rdesc Indicates how many entries in the logical palette were mapped to different entries // in the system palette. This represents the number of entries that this function // remapped to accommodate changes in the system palette since the logical palette // was last realized. } // @pymethod dict|PyCDC|SetROP2|Sets the current drawing mode. static PyObject * ui_dc_set_rop2 (PyObject * self, PyObject * args) { int mode, old_mode; CDC *pDC = ui_dc_object::GetDC (self); if (!pDC) { return NULL; } // @pyparm int|mode||The new drawing mode. if (!PyArg_ParseTuple (args, "i", &mode)) { return NULL; } GUI_BGN_SAVE; old_mode = pDC->SetROP2 (mode);// @pyseemfc CDC|SetROP2 GUI_END_SAVE; return Py_BuildValue ("i", old_mode); } // @pymethod |PyCDC|TextOut|Outputs text to the display context, using the currently selected font. static PyObject *ui_dc_text_out (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; TCHAR *text; PyObject *obtext; DWORD strLen; int x, y; if (!PyArg_ParseTuple (args, "iiO:TextOut", &x, // @pyparm x|int||The x coordinate to write the text to. &y, // @pyparm y|int||The y coordinate to write the text to. &obtext)) // @pyparm text|string||The text to write. return NULL; if (!PyWinObject_AsTCHAR(obtext, &text, FALSE, &strLen)) return NULL; GUI_BGN_SAVE; BOOL ret = pDC->TextOut (x, y, text, strLen); // @pyseemfc CDC|TextOut GUI_END_SAVE; PyWinObject_FreeTCHAR(text); if (!ret) RETURN_API_ERR("CDC::TextOut"); RETURN_NONE; // @rdesc Always none. If the function fails, an exception is raised. } /* struct to dict macro (alpha version) move to win32ui_int eventually */ #define DICTADD(D,ST,M,TYPE) PyDict_SetItemString (D, #M, Py_BuildValue (TYPE, ST.M)) // @pymethod dict|PyCDC|GetTextMetrics|Retrieves the metrics for the current font in this device context. static PyObject * ui_dc_get_text_metrics (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CHECK_NO_ARGS(args); TEXTMETRIC tm; if (!pDC->GetTextMetrics (&tm)) // @pyseemfc CDC|GetTextMetrics RETURN_ERR ("GetTextMetrics failed"); PyObject *d = PyDict_New(); // @rdesc A dictionary of integers, keyed by the following strings: DICTADD (d, tm, tmHeight, "i"); // tmHeight DICTADD (d, tm, tmAscent, "i"); // tmAscent DICTADD (d, tm, tmDescent, "i"); // tmDescent DICTADD (d, tm, tmInternalLeading, "i"); // tmInternalLeading DICTADD (d, tm, tmExternalLeading, "i"); // tmExternalLeading DICTADD (d, tm, tmAveCharWidth, "i"); // tmAveCharWidth DICTADD (d, tm, tmMaxCharWidth, "i"); // tmMaxCharWidth DICTADD (d, tm, tmWeight, "i"); // tmWeight DICTADD (d, tm, tmItalic, "i"); // tmItalic DICTADD (d, tm, tmUnderlined, "i"); // tmUnderlined DICTADD (d, tm, tmStruckOut, "i"); // tmStruckOut DICTADD (d, tm, tmFirstChar, "i"); // tmFirstChar DICTADD (d, tm, tmLastChar, "i"); // tmLastChar DICTADD (d, tm, tmDefaultChar, "i"); // tmDefaultChar DICTADD (d, tm, tmBreakChar, "i"); // tmBreakChar DICTADD (d, tm, tmPitchAndFamily, "i"); // tmPitchAndFamily DICTADD (d, tm, tmCharSet, "i"); // tmCharSet DICTADD (d, tm, tmOverhang, "i"); // tmOverhang DICTADD (d, tm, tmDigitizedAspectX, "i"); // tmDigitizedAspectX DICTADD (d, tm, tmDigitizedAspectY, "i"); // tmDigitizedAspectY return d; } // @pymethod string|PyCDC|GetTextFace|Returns typeface name of the current font. static PyObject * ui_dc_get_text_face (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, ":GetTextFace")) return NULL; TCHAR buf[LF_FACESIZE]; GUI_BGN_SAVE; int ret = pDC->GetTextFace (LF_FACESIZE, buf); // @pyseemfc CDC|GetTextFace GUI_END_SAVE; if (ret == 0) buf[0] = '\0'; return PyWinObject_FromTCHAR(buf); } // @pymethod int|PyCDC|SaveDC|Saves the current state of the device context. Windows manages a stack of state information. // The saved device context can later be restored by using static PyObject * ui_dc_save_dc (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, "")) return NULL; GUI_BGN_SAVE; int ret = pDC->SaveDC(); // @pyseemfc CDC|SaveDC GUI_END_SAVE; if (ret == 0) RETURN_ERR ("SaveDC failed"); else return Py_BuildValue ("i", ret); // @rdesc An integer identifying the context, which can be used by . // An exception is raised if this function fails. } // @pymethod |PyCDC|RestoreDC|Restores the state of the device context. static PyObject * ui_dc_restore_dc (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int saved; // @pyparm int|saved||The id of a previously saved device context. See if (!PyArg_ParseTuple (args, "i", &saved)) return NULL; GUI_BGN_SAVE; BOOL ok = pDC->RestoreDC (saved); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|RestoreDC RETURN_ERR ("RestoreDC failed"); else RETURN_NONE; } // @pymethod (x,y)|PyCDC|MoveTo|Moves the current position to a specified point. static PyObject * ui_dc_move_to (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; // @pyparm (x,y)|point||The point coordinate to move to. // @pyparmalt1 int|x||The x coordinate to move to. // @pyparmalt1 int|y||The y coordinate to move to. int x, y; CPoint prev; if (!PyArg_ParseTuple (args, "ii", &x, &y)) { PyErr_Clear(); if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; } GUI_BGN_SAVE; prev = pDC->MoveTo (x,y); // @pyseemfc CDC|MoveTo GUI_END_SAVE; return Py_BuildValue ("(ii)", prev.x, prev.y); // @rdesc The previous position. } // @pymethod |PyCDC|LineTo|Draws a line to a specified point, using the currently selected pen. static PyObject * ui_dc_line_to (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; // @pyparm (x,y)|point||The point coordinate to draw to. // @pyparmalt1 int|x||The x coordinate to draw to. // @pyparmalt1 int|y||The y coordinate to draw to. int x, y; CPoint prev; if (!PyArg_ParseTuple (args, "ii", &x, &y)) { PyErr_Clear(); if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; } GUI_BGN_SAVE; BOOL ok = pDC->LineTo (x,y); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|LineTo RETURN_ERR ("LineTo failed"); else RETURN_NONE; } // @pymethod (x,y)|PyCDC|DPtoLP|Converts device units into logical units. static PyObject * ui_dc_dp_to_lp (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CPoint pt; // @todo Should really handle list of (x,y) points // @pyparm (x,y)|point||The point to convert // @pyparmalt1 int|x||The x coordinate to convert. // @pyparmalt1 int|y||The y coordinate to convert. if (!PyArg_ParseTuple (args, "ii", &pt.x, &pt.y)) { PyErr_Clear(); if (!PyArg_ParseTuple (args, "(ii)", &pt.x, &pt.y)) return NULL; } GUI_BGN_SAVE; pDC->DPtoLP (&pt, 1); // @pyseemfc CDC|DPtoLP GUI_END_SAVE; return (Py_BuildValue ("(ii)", pt.x, pt.y)); // @rdesc The converted coordinates. } // @pymethod (x,y)|PyCDC|LPtoDP|Converts logical units into device units. static PyObject * ui_dc_lp_to_dp (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; CPoint pt; // should really handle array of (x,y) points // @pyparm (x,y)|point||The point coordinate to convert. // @pyparmalt1 int|x||The x coordinate to convert. // @pyparmalt1 int|y||The y coordinate to convert. if (!PyArg_ParseTuple (args, "ii", &pt.x, &pt.y)) { PyErr_Clear(); if (!PyArg_ParseTuple (args, "(ii)", &pt.x, &pt.y)) return NULL; } GUI_BGN_SAVE; pDC->LPtoDP (&pt, 1); // @pyseemfc CDC|LPtoDP GUI_END_SAVE; return (Py_BuildValue ("(ii)", pt.x, pt.y)); // @rdesc The converted coordinates. } // @pymethod (left, top, right, bottom)|PyCDC|GetClipBox|Retrieves the dimensions of the smallest bounding rectangle around the current clipping boundary. static PyObject * ui_dc_get_clip_box (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, "")) return NULL; CRect rect; GUI_BGN_SAVE; int ret = pDC->GetClipBox (&rect); // @pyseemfc CDC|GetClipBox GUI_END_SAVE; if (ret == ERROR) RETURN_ERR ("GetClipBox failed"); else return Py_BuildValue ("(iiii)", rect.left, rect.top, rect.right, rect.bottom); // @rdesc A tuple of integers specifying the rectangle. } // @pymethod int|PyCDC|GetHandleAttrib|Retrieves the handle of the attribute device context. static PyObject * ui_dc_get_handle_attrib (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, ":GetHandleAttrib")) return NULL; return Py_BuildValue ("i", pDC->m_hAttribDC); } // @pymethod int|PyCDC|GetHandleOutput|Retrieves the handle of the output device context. static PyObject * ui_dc_get_handle_output (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; if (!PyArg_ParseTuple (args, ":GetHandleOutput")) return NULL; return Py_BuildValue ("i", pDC->m_hDC); } // Path methods: // BeginPath // EndPath // StrokePath // FillPath // StrokeAndFillPath // @pymethod |PyCDC|BeginPath|Opens a path bracket in the device context static PyObject * ui_dc_begin_path (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; BOOL ok = pDC->BeginPath(); GUI_END_SAVE; if (!ok) { RETURN_API_ERR ("CDC::BeginPath"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|EndPath|Closes a path bracket and selects the path defined by the bracket into the specified device context static PyObject * ui_dc_end_path (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; BOOL ok = pDC->EndPath(); GUI_END_SAVE; if (!ok) { RETURN_API_ERR ("CDC::EndPath"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|FillPath|Closes any open figures in the current path and fills the path's interior by using the current brush and polygon-filling mode. After its interior is filled, the path is discarded from the device context. static PyObject * ui_dc_fill_path (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; BOOL ok = pDC->FillPath(); GUI_END_SAVE; if (!ok) { RETURN_API_ERR ("CDC::FillPath"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|StrokePath|Renders the specified path by using the current pen. static PyObject * ui_dc_stroke_path (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; BOOL ok = pDC->StrokePath(); GUI_END_SAVE; if (!ok) { RETURN_API_ERR ("CDC::StrokePath"); } else { RETURN_NONE; } } } // @pymethod |PyCDC|StrokeAndFillPath|Closes any open figures in a path, strokes the outline of the path by using the current pen, and fills its interior by using the current brush. The device context must contain a closed path. static PyObject * ui_dc_stroke_and_fill_path (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else if (!PyArg_ParseTuple (args, "")) { return NULL; } else { GUI_BGN_SAVE; BOOL ok = pDC->StrokeAndFillPath(); GUI_END_SAVE; if (!ok) { RETURN_API_ERR ("CDC::StrokeAndFillPath"); } else { RETURN_NONE; } } } // @pymethod int|PyCDC|IsPrinting|Returns 1 if the DC is currently printing, else 0 static PyObject * ui_dc_is_printing (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) { return NULL; } else { GUI_BGN_SAVE; int rc = pDC->IsPrinting(); GUI_END_SAVE; return Py_BuildValue ("i", rc); } } // @pymethod x, y|PyCDC|ScaleWindowExt|Modifies the window extents relative to the current values. static PyObject * ui_dc_scale_window_ext (PyObject * self, PyObject * args) { CDC *pDC = ui_dc_object::GetDC (self); if (!pDC) { return NULL; } else { int xn,xd,yn,yd; if (!PyArg_ParseTuple (args, "iiii", &xn, &xd, &yn, &yd)) { return NULL; } else { GUI_BGN_SAVE; CSize r = pDC->ScaleWindowExt (xn, xd, yn, yd); GUI_END_SAVE; return Py_BuildValue ("(ii)", r.cx, r.cy); } } } // @pymethod x, y|PyCDC|ScaleViewportExt|Modifies the viewport extents relative to the current values. static PyObject * ui_dc_scale_viewport_ext (PyObject * self, PyObject * args) { CDC *pDC = ui_dc_object::GetDC (self); if (!pDC) { return NULL; } else { int xn,xd,yn,yd; if (!PyArg_ParseTuple (args, "iiii", &xn, &xd, &yn, &yd)) { return NULL; } else { GUI_BGN_SAVE; CSize r = pDC->ScaleViewportExt (xn, xd, yn, yd); GUI_END_SAVE; return Py_BuildValue ("(ii)", r.cx, r.cy); } } } // Printing functions // @pymethod |PyCDC|AbortDoc|Aborts a print job static PyObject *ui_dc_abort_doc(PyObject * self, PyObject * args) { CHECK_NO_ARGS2(args, AbortDoc); CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; GUI_BGN_SAVE; pDC->AbortDoc(); GUI_END_SAVE; RETURN_NONE; } // @pymethod |PyCDC|EndDoc|Finishes spooling the document and starts printing it static PyObject *ui_dc_end_doc(PyObject * self, PyObject * args) { CHECK_NO_ARGS2(args, EndDoc); CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; GUI_BGN_SAVE; int err = pDC->EndDoc(); GUI_END_SAVE; if (err < 0) { char msg[64]; sprintf(msg, "EndDoc failed (error code %d)", err); PyErr_SetString(ui_module_error, msg); return NULL; } RETURN_NONE; } // @pymethod |PyCDC|EndPage|Finishes a page on a printer DC static PyObject *ui_dc_end_page(PyObject * self, PyObject * args) { CHECK_NO_ARGS2(args, EndPage); CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; GUI_BGN_SAVE; int err = pDC->EndPage(); GUI_END_SAVE; if (err < 0) { char msg[64]; sprintf(msg, "EndDoc failed (error code %d)", err); PyErr_SetString(ui_module_error, msg); return NULL; } RETURN_NONE; } // @pymethod |PyCDC|StartDoc|Starts spooling a document to a printer DC static PyObject *ui_dc_start_doc(PyObject * self, PyObject * args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; // @pyparm string|docName||The document name // @pyparm string|outputFile||The output file name. Use this to spool to a file. Omit to send to the printer. TCHAR *docName=NULL, *outputFile = NULL; PyObject *obdocName, *oboutputFile=Py_None; if (!PyArg_ParseTuple(args, "O|O:StartDoc", &obdocName, &oboutputFile)) return NULL; if (!PyWinObject_AsTCHAR(obdocName, &docName, FALSE)) return NULL; if (!PyWinObject_AsTCHAR(oboutputFile, &outputFile, TRUE)){ PyWinObject_FreeTCHAR(docName); return NULL; } DOCINFO info; info.cbSize = sizeof(DOCINFO); memset(&info, 0, sizeof(DOCINFO)); info.lpszDocName = docName; info.lpszOutput = outputFile; GUI_BGN_SAVE; int rc = pDC->StartDoc(&info); GUI_END_SAVE; PyWinObject_FreeTCHAR(docName); PyWinObject_FreeTCHAR(outputFile); if ( rc < 0) { RETURN_ERR("StartDoc failed"); } RETURN_NONE; } // @pymethod |PyCDC|StartPage|Starts a new page on a printer DC static PyObject *ui_dc_start_page(PyObject * self, PyObject * args) { CHECK_NO_ARGS2(args, StartPage); CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; GUI_BGN_SAVE; int rc = pDC->StartPage(); GUI_END_SAVE; if ( rc <= 0) RETURN_ERR("StartPage failed"); RETURN_NONE; } ///////////////////////////////////////////////////////////////////// // // DC methods contributed by: Kleanthis Kleanthous (kk@epsilon.com.gr) // @pymethod |PyCDC|IntersectClipRect|Creates a new clipping region by forming the intersection of the current region and the rectangle specified // @rdesc region type as integer static PyObject * ui_dc_intersect_clip_rect(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; if (!PyArg_ParseTuple (args, "(iiii):IntersectClipRect", &rect.left, &rect.top, &rect.right, &rect.bottom // @pyparm (left, top, right, bottom)|rect||Specifies the bounding rectangle, in logical units. )) return NULL; GUI_BGN_SAVE; int type=pDC->IntersectClipRect(&rect); GUI_END_SAVE; // @pyseemfc CDC|IntersectClipRect return Py_BuildValue("i",type); } // @pymethod (int)|PyCDC|SetPolyFillMode|Sets the polygon-filling mode. // @rdesc The previous PolyFillMode as integer static PyObject * ui_dc_set_poly_fill_mode(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int nPolyFillMode; // @pyparm (x,y)|point||The new origin in device units. if (!PyArg_ParseTuple (args, "i",&nPolyFillMode)) return NULL; GUI_BGN_SAVE; int pr = pDC->SetPolyFillMode(nPolyFillMode); // @pyseemfc CDC|SetPolyFillMode GUI_END_SAVE; return Py_BuildValue ("i", pr); // @rdesc The previous PolyFillMode. } // @pymethod |PyCDC|Polyline|Draws a Polyline. static PyObject *ui_dc_polyline (PyObject *self, PyObject *args) { PyObject * point_list; CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; // @pyparm [(x, y), ...]|points||A sequence of points if (!PyArg_ParseTuple(args, "O:Polyline", &point_list)) { return NULL; } else if (!PySequence_Check(point_list)) { RETURN_TYPE_ERR("Argument must be a list of points"); } else { // Convert the list of point tuples into an array of POINT structs Py_ssize_t num = PySequence_Length(point_list); POINT * point_array = new POINT[num]; for (Py_ssize_t i=0; i < num; i++) { PyObject * point_tuple = PySequence_GetItem (point_list, i); if (!PyTuple_Check (point_tuple) || PyTuple_Size (point_tuple) != 2) { PyErr_SetString (PyExc_ValueError, "point list must be a list of (x,y) tuples"); delete[] point_array; return NULL; } else { long x, y; PyObject *px, *py; px = PyTuple_GetItem (point_tuple, 0); py = PyTuple_GetItem (point_tuple, 1); if ((!PyInt_Check(px)) || (!PyInt_Check(py))) { PyErr_SetString (PyExc_ValueError, "point list must be a list of (x,y) tuples"); delete[] point_array; return NULL; } else { x = PyInt_AsLong (px); y = PyInt_AsLong (py); point_array[i].x = x; point_array[i].y = y; } } } // we have an array of POINT structs, now we // can finally draw the polyline. GUI_BGN_SAVE; BOOL ret = pDC->Polyline(point_array, PyWin_SAFE_DOWNCAST(num, Py_ssize_t, int)); GUI_END_SAVE; delete[] point_array; if (!ret) { RETURN_API_ERR("CDC::Polyline"); } else { RETURN_NONE; } } } // @pymethod x, y|PyCDC|OffsetWindowOrg|Modifies the coordinates of the window origin relative to the coordinates of the current window origin. // @rdesc The previous origin as a tuple (x,y) static PyObject * ui_dc_offset_window_org(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC)return NULL; int x,y; // @pyparm int, int|x,y||The new origin offset. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; GUI_BGN_SAVE; CPoint old_org = pDC->OffsetWindowOrg(x, y); GUI_END_SAVE; return Py_BuildValue("(ii)", old_org.x, old_org.y); } // @pymethod x, y|PyCDC|OffsetViewportOrg|Modifies the coordinates of the viewport origin relative to the coordinates of the current viewport origin // @rdesc The previous viewport origin as a tuple (x,y) static PyObject * ui_dc_offset_viewport_org(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC)return NULL; int x,y; // @pyparm int, int|x,y||The new origin offset. if (!PyArg_ParseTuple (args, "(ii)", &x, &y)) return NULL; GUI_BGN_SAVE; CPoint old_org = pDC->OffsetViewportOrg(x, y); GUI_END_SAVE; return Py_BuildValue("(ii)", old_org.x, old_org.y); } // @pymethod obRgn|PyCDC|SelectClipRgn|Selects the given region as the current clipping region for the device context // @rdesc The return value specifies the region's complexity (integer) static PyObject * ui_dc_select_clip_rgn(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC)return NULL; PyObject *objRgn = Py_None; if (!PyArg_ParseTuple(args,"O:SelectClipRgn",&objRgn)) return NULL; CRgn *pRgn = PyCRgn::GetRgn(objRgn); if (!pRgn) return NULL; GUI_BGN_SAVE; int r=pDC->SelectClipRgn(pRgn); GUI_END_SAVE; return Py_BuildValue("i",r); } // @pymethod rc|PyCDC|Rectangle|Draws a rectangle using the current pen. The interior of the rectangle is filled using the current brush. static PyObject * ui_dc_rectangle(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC)return NULL; RECT rect; if (!PyArg_ParseTuple(args, "(iiii)", &rect.left,&rect.top, &rect.right,&rect.bottom)) return NULL; BOOL b=pDC->Rectangle(rect.left,rect.top,rect.right,rect.bottom); if(!b)RETURN_API_ERR("CDC::Rectangle"); RETURN_NONE; } // @pymethod s,rc,forat|PyCDC|DrawText|Formats text in the given rectangle // @rdesc Height of text in pixels static PyObject * ui_dc_draw_text(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC)return NULL; char *psz; RECT rect; UINT nFormat=DT_SINGLELINE|DT_CENTER|DT_VCENTER; if (!PyArg_ParseTuple(args, "s(iiii)|i",&psz, // @pyparm string|s||The desired output string // @pyparm (int, int, int, int)|tuple||The bounding rectangle in the form: // (left, top, right, bottom) expressed in logical units (depending on // selected coordinate system - see ) &rect.left,&rect.top, &rect.right,&rect.bottom, // @pyparm int|format||Specifies one or more bit-or'd format values, such as // DT_BOTTOM, DT_CENTERDT_RIGHT, DT_VCENTER. For a complete list, see // the Microsoft Win32 API documentation. &nFormat)) return NULL; CString str(psz); int height=pDC->DrawText(str,&rect,nFormat); // @rdesc The return value is the height of the text, in logical units. // If DT_VCENTER or DT_BOTTOM is specified, the return value is the // offset from rect.top to the bottom of the drawn text. // If the function fails, the return value is zero (no Python exception is thrown) return Py_BuildValue("i",height); // @ex Example|import win32ui // import win32con // INCH = 1440 # twips - 1440 per inch allows fine res // def drawtext_test(): // dc = win32ui.CreateDC() // dc.CreatePrinterDC() # ties to default printer // dc.StartDoc('My Python Document') // dc.StartPage() // // # note: upper left is 0,0 with x increasing to the right, // # and y decreasing (negative) moving down // dc.SetMapMode(win32con.MM_TWIPS) // // # Centers "TEST" about an inch down on page // dc.DrawText('TEST', (0,INCH*-1,INCH*8,INCH*-2), win32con.DT_CENTER ) // dc.EndPage() // dc.EndDoc() // del dc } // @pymethod |PyCDC|StretchBlt|Copies a bitmap from the source device context to this device context. static PyObject * ui_dc_stretch_blt (PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; int x, y, width, height, xsrc, ysrc,widthsrc, heightsrc; DWORD rop; PyObject *dc_ob; if (!PyArg_ParseTuple (args, "(ii)(ii)O(ii)(ii)i", &x, &y, // @pyparm (x,y)-ints|destPos||The logical x,y coordinates of the upper-left corner of the destination rectangle. &width, &height, // @pyparm (width, height)-ints|size||Specifies the width and height (in logical units) of the destination rectangle and source bitmap. &dc_ob, // @pyparm |dc||Specifies the PyCDC object from which the bitmap will be copied. It must be None if rop specifies a raster operation that does not include a source. &xsrc, &ysrc, // @pyparm (xSrc, ySrc)-ints|srcPos||Specifies the logical x,y coordinates of the upper-left corner of the source bitmap. &widthsrc, &heightsrc, // @pyparm (widthsrc, heightsrc)-ints|size||Specifies the width and height (in logical units) of the destination rectangle and source bitmap. &rop)) // @pyparm int|rop||Specifies the raster operation to be performed. See the win32 api documentation for details. return NULL; if (!ui_base_class::is_uiobject (dc_ob, &ui_dc_object::type)) RETURN_TYPE_ERR("The 'O' param must be a PyCDC object"); CDC *pSrcDC = NULL; if (dc_ob!=Py_None) { pSrcDC = ui_dc_object::GetDC(dc_ob); if (!pSrcDC) RETURN_ERR("The source DC is invalid"); } GUI_BGN_SAVE; int prevMode=pDC->SetStretchBltMode(COLORONCOLOR); BOOL ok = pDC->StretchBlt(x, y, width, height, pSrcDC, xsrc, ysrc,widthsrc, heightsrc, rop); pDC->SetStretchBltMode(prevMode); GUI_END_SAVE; if (!ok) // @pyseemfc CDC|StretchBlt RETURN_ERR("StretchBlt failed"); RETURN_NONE; } // End of kk contributed methods! // @pymethod |PyCDC|DrawFrameControl|Draws a frame control of the specified type and style. static PyObject * ui_dc_draw_frame_control(PyObject *self, PyObject *args) { CDC *pDC = ui_dc_object::GetDC(self); if (!pDC) return NULL; RECT rect; int typ, state; if (!PyArg_ParseTuple (args, "(iiii)ii:DrawFrameControl", &rect.left, &rect.top, &rect.right, &rect.bottom, // @pyparm (left, top, right, bottom)|rect||Specifies the bounding rectangle, in logical units. &typ, // @pyparm int|typ|| &state // @pyparm int|state|| )) return NULL; GUI_BGN_SAVE; BOOL ok=pDC->DrawFrameControl(&rect, typ, state); GUI_END_SAVE; if (!ok) RETURN_ERR("DrawFrameControl failed"); // @pyseemfc CDC|DrawFrameControl RETURN_NONE; } ///////////////////////////////////////////////////////////////////// // DC Methods // @object PyCDC|A Device Context. Encapsulates an MFC class. static struct PyMethodDef ui_dc_methods[] = { {"AbortDoc", ui_dc_abort_doc, 1}, // @pymeth AbortDoc|Aborts a print job {"Arc", ui_dc_arc, 1}, // @pymeth Arc|Draws an arc. {"BeginPath", ui_dc_begin_path, 1}, // @pymeth BeginPath|Opens a path bracket in the device context {"BitBlt", ui_dc_bitblt, 1}, // @pymeth BitBlt|Copies a bitmap {"Chord", ui_dc_chord, 1}, // @pymeth Chord|Draws a chord. {"CreateCompatibleDC", ui_dc_object::create_compatible_dc, 1}, // @pymeth CreateCompatibleDC|Creates a memory DC compatible with this DC. {"CreatePrinterDC", ui_dc_object::create_printer_dc, 1}, // @pymeth CreatePrinterDC|Creates a device context for a specific printer {"DeleteDC", ui_dc_delete_dc, 1}, // @pymeth DeleteDC|Deletes all resources associated with a device context. {"DPtoLP", ui_dc_dp_to_lp, 1}, // @pymeth DPtoLP|Convert from device points to logical points. {"Draw3dRect", ui_dc_draw3drect, 1}, // @pymeth Draw3dRect|Draws a three-dimensional rectangle. {"DrawFocusRect", ui_dc_draw_focus_rect, 1}, // @pymeth DrawFocusRect|Draws a rectangle in the style used to indicate the rectangle has focus {"DrawFrameControl", ui_dc_draw_frame_control,1}, // @pymeth DrawFrameControl|Draws a frame control of the specified type and style. {"DrawIcon", ui_dc_draw_icon, 1}, // @pymeth DrawIcon|Draws an icon on the DC. {"DrawText", ui_dc_draw_text,1}, // @pymeth DrawText|Formats text in the given rectangle {"Ellipse", ui_dc_ellipse, 1}, // @pymeth Ellipse|Draws an Ellipse. {"EndDoc", ui_dc_end_doc, 1}, // @pymeth EndDoc|Finishes spooling the document and starts printing it {"EndPage", ui_dc_end_page, 1}, // @pymeth EndPage|Finishes a page on a printer DC {"EndPath", ui_dc_end_path, 1}, // @pymeth EndPath|Closes a path bracket and selects the path defined by the bracket into the specified device context {"ExtTextOut", ui_dc_ext_text_out, 1}, //@pymeth ExtTextOut|Writes text to the DC. {"FillPath", ui_dc_fill_path, 1}, // @pymeth FillPath|Closes any open figures in the current path and fills the path's interior by using the current brush and polygon-filling mode. {"FillRect", ui_dc_fillrect, 1}, // @pymeth FillRect|Fills a given rectangle with the specified brush {"FillSolidRect", ui_dc_fillsolidrect, 1}, // @pymeth FillSolidRect|Fills the given rectangle with the specified solid color. {"FrameRect", ui_dc_framerect, 1}, // @pymeth FrameRect|Draws a border around the rectangle specified by rect {"GetBrushOrg", ui_dc_get_brush_org, 1}, // @pymeth GetBrushOrg|Retrieves the origin (in device units) of the brush currently selected for the device context. {"GetClipBox", ui_dc_get_clip_box, 1}, // @pymeth GetClipBox|Retrives the current clipping region. {"GetCurrentPosition", ui_dc_get_current_position, 1}, // @pymeth GetCurrentPosition|Retrieves the current position (in logical coordinates). {"GetDeviceCaps", ui_dc_get_device_caps, 1}, // @pymeth GetDeviceCaps|Retrieves current device capabilities. {"GetHandleAttrib", ui_dc_get_handle_attrib, 1}, // @pymeth GetHandleAttrib|Retrieves the handle of the attribute device context. {"GetHandleOutput", ui_dc_get_handle_output, 1}, // @pymeth GetHandleOutput|Retrieves the handle of the output device context. {"GetMapMode", ui_dc_get_map_mode, 1}, //@pymeth GetMapMode|Gets the mapping mode for the device context. {"GetNearestColor", ui_dc_get_nearest_color, 1}, // @pymeth GetNearestColor|Returns the closest color a device can map. {"GetPixel", ui_dc_get_pixel, 1}, // @pymeth GetPixel|Returns the value of a pixel at a location {"GetSafeHdc", ui_dc_get_safe_hdc, 1}, // @pymeth GetSafeHdc|Returns the underlying windows handle for the DC object. {"GetTextExtent", ui_dc_get_text_extent, 1}, // @pymeth GetTextExtent|Calculates the size of the string. {"GetTextExtentPoint", ui_dc_get_text_extent, 1}, // @pymeth GetTextExtentPoint|Alias for GetTextExtent - Calculates the size of the string. {"GetTextFace", ui_dc_get_text_face, 1}, // @pymeth GetTextFace|Retrieves the name of the current font. {"GetTextMetrics", ui_dc_get_text_metrics, 1}, // @pymeth GetTextMetrics|Retrieves the metrics for the current font. {"GetViewportExt", ui_dc_get_viewport_ext, 1}, // @pymeth GetViewportExt|Gets the viewport extent of the device context {"GetViewportOrg", ui_dc_get_viewport_org, 1}, // @pymeth GetViewportOrg|Gets the viewport origin of the device context {"GetWindowExt", ui_dc_get_window_ext, 1}, // @pymeth GetWindowExt|Gets the window extent of the device context {"GetWindowOrg", ui_dc_get_window_org, 1}, // @pymeth GetWindowOrg|Retrieves the x- and y-coordinates of the origin of the window associated with the device context. {"IntersectClipRect", ui_dc_intersect_clip_rect, 1}, // @pymeth IntersectClipRect|Creates a new clipping region by forming the intersection of the current region and the rectangle specified {"IsPrinting", ui_dc_is_printing, 1}, // @pymeth IsPrinting|Returns 1 if the DC is currently printing, else 0 {"LineTo", ui_dc_line_to, 1}, // @pymeth LineTo|Draws a line to a specified point. {"LPtoDP", ui_dc_lp_to_dp, 1}, // @pymeth LPtoDP|Convert from logical points to device points {"MoveTo", ui_dc_move_to, 1}, // @pymeth MoveTo|Moves the current position to a specifed point. {"OffsetWindowOrg", ui_dc_offset_window_org,1}, // @pymeth OffsetWindowOrg|Modifies the coordinates of the window origin relative to the coordinates of the current window origin. {"OffsetViewportOrg", ui_dc_offset_viewport_org,1}, // @pymeth OffsetViewportOrg|Modifies the coordinates of the viewport origin relative to the coordinates of the current viewport origin {"PatBlt", ui_dc_patblt, 1}, // @pymeth PatBlt|Creates a bit pattern on the device. {"Pie", ui_dc_pie, 1}, // @pymeth Pie|Draws a pie shape with specific starting and ending points in a rectangle {"PolyBezier", ui_dc_poly_bezier, 1}, // @pymeth PolyBezier|Draws one or more Bezier splines. {"Polygon", ui_dc_polygon, 1}, // @pymeth Polygon|Draws an Polygon. {"Polyline", ui_dc_polyline, 1}, // @pymeth Polyline|Draws a Polyline. {"RealizePalette", ui_dc_realize_palette, 1}, // @pymeth RealizePalette|Maps palette entries in the current logical palette to the system palette. {"Rectangle", ui_dc_rectangle,1}, // @pymeth Rectangle|Draws a rectangle using the current pen. The interior of the rectangle is filled using the current brush. {"RectVisible", ui_dc_rect_visible, 1}, // @pymeth RectVisible|Determines if a rectangle is currently visisble in the viewport. {"RestoreDC", ui_dc_restore_dc, 1}, // @pymeth RestoreDC|Restores a saved DC. {"SaveDC", ui_dc_save_dc, 1}, // @pymeth SaveDC|Saves a DC. {"ScaleWindowExt", ui_dc_scale_window_ext, 1}, // @pymeth ScaleWindowExt|Modifies the window extents relative to the current values. {"ScaleViewportExt", ui_dc_scale_viewport_ext, 1}, // @pymeth ScaleViewportExt|Modifies the viewport extents relative to the current values. {"SelectClipRgn", ui_dc_select_clip_rgn,1}, // @pymeth SelectClipRgn|Selects the given region as the current clipping region for the device context {"SelectObject", ui_dc_select_object, 1}, // @pymeth SelectObject|Selects an object into the DC. {"SelectPalette", ui_dc_select_palette, 1}, // @pymeth SelectObject|Selects the logical palette. {"SetBkColor", ui_dc_set_bk_color, 1}, // @pymeth SetBkColor|Sets the background color. {"SetBkMode", ui_dc_set_bk_mode, 1}, // @pymeth SetBkMode|Sets the background mode. {"SetBrushOrg", ui_dc_set_brush_org, 1}, // @pymeth SetBrushOrg|Specifies the origin that GDI will assign to the next brush that the application selects into the device context. {"SetGraphicsMode", ui_dc_set_graphics_mode, 1}, // @pymeth SetGraphicsMode|Sets the graphics mode for the specified device context {"SetMapMode", ui_dc_set_map_mode, 1}, // @pymeth SetMapMode|Sets the device mapping mode. {"SetPixel", ui_dc_setpixel, 1}, // @pymeth SetPixel|Set a pixel to a color {"SetPolyFillMode", ui_dc_set_poly_fill_mode, 1}, // @pymeth SetPolyFillMode|Sets the polygon-filling mode. {"SetROP2", ui_dc_set_rop2, 1}, // @pymeth SetROP2|Sets the current drawing mode. {"SetTextAlign", ui_dc_set_text_align, 1}, // @pymeth SetTextAlign|Sets the text alignment. {"SetTextColor", ui_dc_set_text_color, 1}, // @pymeth SetTextColor|Sets the text foreground color. {"SetWindowExt", ui_dc_set_window_ext, 1}, // @pymeth SetWindowExt|Sets the extents of the window. {"SetWindowOrg", ui_dc_set_window_org, 1}, // @pymeth SetWindowOrg|Sets the window origin of the device context {"SetViewportExt", ui_dc_set_viewport_ext, 1}, // @pymeth SetViewportExt|Sets the extents of the window's viewport. {"SetViewportOrg", ui_dc_set_viewport_org, 1}, // @pymeth SetViewportOrg|Sets the viewport origin of the device context {"SetWorldTransform", ui_dc_set_world_transform, 1}, // @pymeth SetWorldTransform|sets a two-dimensional linear transformation between world space and page space for the specified device context. {"StartDoc", ui_dc_start_doc, 1}, // @pymeth StartDoc|Starts spooling a document to a printer DC {"StartPage", ui_dc_start_page, 1}, // @pymeth StartPage|Starts a new page on a printer DC {"StretchBlt", ui_dc_stretch_blt,1}, // @pymeth StretchBlt|Copies a bitmap from the source device context to this device context. {"StrokeAndFillPath", ui_dc_stroke_and_fill_path, 1}, // @pymeth StrokeAndFillPath|Closes any open figures in a path, strokes the outline of the path by using the current pen, and fills its interior by using the current brush. The device context must contain a closed path. {"StrokePath", ui_dc_stroke_path, 1}, // @pymeth StrokePath|Renders the specified path by using the current pen. {"TextOut", ui_dc_text_out, 1}, // @pymeth TextOut|Writes text to the DC. {NULL, NULL} }; ui_type_CObject ui_dc_object::type("PyCDC", &ui_assoc_object::type, RUNTIME_CLASS(CDC), sizeof(ui_dc_object), PYOBJ_OFFSET(ui_dc_object), ui_dc_methods, GET_PY_CTOR(ui_dc_object));