Support Board
Date/Time: Fri, 07 Mar 2025 00:55:57 +0000
DrawText (winapi) problem in sc.p_GDIFunction, possible bug.
View Count: 822
[2022-02-18 19:44:16] |
User978306 - Posts: 4 |
Hi, Support. Trying to create text output at MainPriceGraph, but can not.. Sample SierraChart study: void draw_text_function(HWND hwnd, HDC hdc, SCStudyInterfaceRef sc);
SCSFExport scsf_draw_text_test(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "draw text test"; sc.UpdateAlways = 1; sc.AutoLoop = 0; sc.GraphRegion = 0; sc.p_GDIFunction = draw_text_function; return; } } void draw_text_function(HWND hwnd, HDC hdc, SCStudyInterfaceRef sc) { RECT rc; ::GetClientRect(hwnd, &rc); ::InflateRect(&rc, -300, -300); int old_mode = ::SetMapMode(hdc, MM_TEXT); TCHAR font_face[] = "Consolas"; long font_height = -MulDiv(18, ::GetDeviceCaps(hdc, LOGPIXELSY), 72); HFONT font = ::CreateFontA(font_height, 0, 0, 0, FW_SEMIBOLD, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, font_face); if (font == nullptr) sc.AddMessageToLog("Create study font operatoin error!", 1); HGDIOBJ old_font = ::SelectObject(hdc, font); std::stringstream ss; ss.str("test output string"); int old_bk_mode = ::SetBkMode(hdc, TRANSPARENT); ::SetTextColor(hdc, RGB(255, 0, 0)); int result = ::DrawTextA(hdc, ss.str().c_str(), (int)ss.str().length(), &rc, DT_VCENTER | DT_CENTER | DT_SINGLELINE); HPEN pen = ::CreatePen(PS_SOLID, 1, RGB(204, 204, 204)); ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); HGDIOBJ old_pen = ::SelectObject(hdc, pen); Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); ::DeleteObject(font); ::DeleteObject(pen); ::SetBkMode(hdc, old_bk_mode); ::SelectObject(hdc, old_font); ::SelectObject(hdc, old_pen); ::SetMapMode(hdc, old_mode); ::DeleteObject(font); ::DeleteObject(pen); } First attachment contains screenshot of chart with applied study, can see empty rectangle only. For check, I have created a template VS windows application project and placed inside WM_PAINT block absolutely same code from draw_text_function , have a correct output, can be found in second attachment. Code: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rc; GetClientRect(hWnd, &rc); InflateRect(&rc, -300, -300); WCHAR lpsz_face[] = L"Consolas"; long font_height = -MulDiv(26, ::GetDeviceCaps(hdc, LOGPIXELSY), 72); HFONT font = ::CreateFontW(font_height, 0, 0, 0, FW_SEMIBOLD, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY, FF_DONTCARE | DEFAULT_PITCH, lpsz_face); HGDIOBJ old_font = ::SelectObject(hdc, font); std::wstringstream ss; ss << L"sample text output"; int old_bk_mode = ::SetBkMode(hdc, TRANSPARENT); ::SetTextColor(hdc, RGB(255, 0, 0)); int result = ::DrawTextW(hdc, (LPWSTR)ss.str().c_str(), (int)ss.str().length(), &rc, DT_CENTER| DT_VCENTER | DT_SINGLELINE); HPEN pen = ::CreatePen(PS_SOLID, 1, RGB(204, 204, 204)); ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); ::SelectObject(hdc, pen); Rectangle(hdc, rc.left,rc.top,rc.right,rc.bottom); ::DeleteObject(font); ::DeleteObject(pen); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } |
![]() ![]() |
[2022-02-20 11:46:09] |
Sierra_Chart Engineering - Posts: 18672 |
We have looked into this. Refer to the code example below. Use ::TextOutW. In the next release of Sierra Chart it will also solve a problem where an exception was occurring when unloading a study DLL which has a custom drawing function. Also take note of the new placement for; sc.p_GDIFunction = DrawToChart;
#include "sierrachart.h"
// SCDLLName("GDI Example") // This file demonstrates the functionality to use the Windows Graphics Device // Interface (GDI) with ACSIL to freely draw inside of the chart window // Windows GDI documentation can be found here: // http://msdn.microsoft.com/en-nz/library/windows/desktop/dd145203%28v=vs.85%29.aspx /*==========================================================================*/ // Drawing function declaration void DrawToChart(HWND WindowHandle, HDC DeviceContext, SCStudyInterfaceRef sc); /*==========================================================================*/ SCSFExport scsf_DrawToChartExample(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Draw To Chart Example"; sc.AutoLoop = 0; return; } // This is where we specify the drawing function. This function will be called // when the study graph is drawn on the chart. We are placing this after // if (sc.SetDefaults). So in case the study DLL is unloaded and reloaded, // this will continue to be set to the correct address. sc.p_GDIFunction = DrawToChart; } /*==========================================================================*/ // This is the actual drawing function. This function is specified by the // "sc.p_GDIFunction" member in the main study function above. This drawing // function is called when Sierra Chart draws the study on the chart. This // will only occur after there has been a call to the main "scsf_" study // function which is defined above. // This drawing function has access to the ACSIL "sc." structure. // However, any changes to the variable members will have no effect. void DrawToChart(HWND WindowHandle, HDC DeviceContext, SCStudyInterfaceRef sc ) { //Create a Yellow brush HBRUSH Brush = CreateSolidBrush(RGB(255,255,0)); //Select the brush into the device context HGDIOBJ PriorBrush = SelectObject(DeviceContext, Brush); //Draw a rectangle at the top left of the chart Rectangle(DeviceContext, sc.StudyRegionLeftCoordinate + 5, sc.StudyRegionTopCoordinate + 5, sc.StudyRegionLeftCoordinate + 200, sc.StudyRegionTopCoordinate + 200); int RightCoordinate = sc.StudyRegionRightCoordinate; //Remove the brush from the device context and put the prior brush back in. This is critical! SelectObject(DeviceContext,PriorBrush); //Delete the brush. This is critical! If you do not do this, you will end up with // a GDI leak and crash Sierra Chart. DeleteObject(Brush); ::SetTextAlign(DeviceContext, TA_NOUPDATECP); //Must use the wide character version ::TextOutW(DeviceContext, 250, 250, L"Hello.", 6); return; } /*==========================================================================*/ Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing Date Time Of Last Edit: 2022-02-20 11:49:17
|
To post a message in this thread, you need to log in with your Sierra Chart account: