I am using visual studio 2017 update 15.3. i have compile the following code but get invalid font handle . return HFONT handle as 0xffffffff045875ca;
#include "stdafx.h"
#include "afxwin.h"
#include "Windows.h"
int main()
{
CFont font;
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT)); // zero out structure
lf.lfHeight = 12; // request a 12-pixel-height font
_tcsncpy_s(lf.lfFaceName, LF_FACESIZE,
_T("Arial"), 7); // request a face name "Arial"
HFONT hFont = CreateFontIndirect(&lf);
return 0;
}
It seems you are using a CFont object from MFC, but are creating a font using the Windows API directly. Calling the global function CreateFontIndirect does not change the unrelated CFont instance font, instead you should use CFont::CreateFontIndirect:
CFont font;
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT)); // zero out structure
lf.lfHeight = 12; // request a 12-pixel-height font
_tcsncpy_s(lf.lfFaceName, LF_FACESIZE,
_T("Arial"), 7); // request a face name "Arial"
font.CreateFontIndirect(&lf);
Related
I need to get an array of pixel color data values of a picture captured from the window, and from a file (.bmp).
I checked through a debugger with breakpoints. The HBITMAP_ToPixelData() method with the HBITMAP created from the file, returns an array with the correct values, but if the HBITMAP created by capturing, the returned array is empty, all values are zero, while the "success" variable is also zero. GetDIBits() for some reason does not work, although the same HBITMAP is correctly transferred to the clipboard and inserted into the photo editor. What could be the problem?
Main.cpp code:
#include <windows.h>
#include <iostream>
#include <vector>
#include "ImageProcessing.h"
using namespace std;
int main()
{
ImageProcessing a1;
HBITMAP hbmp1 = a1.CaptureWindow(L"Notepad");
vector<unsigned char> p_data1 = a1.HBITMAP_ToPixelData(hbmp1);
HBITMAP hbmp2 = a1.HBITMAP_FromFile();
vector<unsigned char> p_data2 = a1.HBITMAP_ToPixelData(hbmp2);
}
ImageProcessing.h code:
#pragma once
#include <vector>
#include <windows.h>
using namespace std;
class ImageProcessing
{
#pragma once
public:
HBITMAP HBITMAP_FromFile()
{
wstring a = L"C:/pic.bmp";
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, a.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
return hBitmap;
}
vector<unsigned char> HBITMAP_ToPixelData(HBITMAP hbmp)
{
BITMAP bmp = {};
BITMAPINFO bmp_info = {};
vector <unsigned char> Pixels = vector <unsigned char>();
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hbmp);
CloseClipboard();
HDC DC = CreateCompatibleDC(NULL);
HGDIOBJ old_bmp = SelectObject(DC, hbmp);
GetObject(hbmp, sizeof(bmp), &bmp);
int width = bmp.bmWidth;
int height = bmp.bmHeight;
bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp_info.bmiHeader.biWidth = width;
bmp_info.bmiHeader.biHeight = height;
bmp_info.bmiHeader.biPlanes = 1;
bmp_info.bmiHeader.biBitCount = 24;
bmp_info.bmiHeader.biCompression = BI_RGB;
bmp_info.bmiHeader.biSizeImage = width * 3 * height;
Pixels.resize(bmp_info.bmiHeader.biSizeImage);
int success = GetDIBits(DC, hbmp, 0, width, &Pixels[0], &bmp_info, DIB_RGB_COLORS);
SelectObject(DC, old_bmp);
DeleteDC(DC);
return Pixels;
}
HBITMAP CaptureWindow(wstring window_title)
{
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
HWND hwnd = FindWindow(NULL, (window_title.c_str()));
if (hwnd == NULL)
{
return NULL;
}
// get window dimentions
RECT windowsize;
GetClientRect(hwnd, &windowsize);
int w = windowsize.right;
int h = windowsize.bottom;
// copy window to bitmap
HDC hdc = GetDC(hwnd);
HDC hCaptureDC = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, w, h);
HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
BOOL bOK = BitBlt(hCaptureDC, 0, 0, w, h, hdc, 0, 0, SRCCOPY);
SelectObject(hCaptureDC, hOld);
DeleteDC(hCaptureDC);
ReleaseDC(hwnd, hdc);
return hBitmap;
}
};
I need to create Rounded Rectangle Buttons in MFC. I tried several resources but did not found the correct way of explanation. Even in **Code Project ** I founded circular or elliptical buttons.
Please suggest how we can create Rounded Rectangle Buttons or any other article
My answers are...
1. Use Skin Library.
I usually use Codejock SkinFramework.
That's ver easy. Include XTSkinFrameworkPro.h in your stdafx.h then load skin file before your dialog is invoked.
XTPSkinManager()->LoadSkin(_T("..."));
2-1. Draw by yourself.
Most simple one is here. Read it first.
https://vcpptips.wordpress.com/tag/owner-draw-button-control/
Then use this code for making round button. It would be nicer if you slide the label text 1px to right-bottom when they hit the button.
http://www.codeproject.com/Articles/11683/CRoundButton-A-fancy-graphical-button
2-2. Draw by yourself. (Use bitmap)
The other one is using bitmap button. Make a bitmap image of rounded button then set it to your button.
how to add bitmap image to buttons in MFC?
Exsample:
Save below as a SimpleBitmapButton.h and include it in your project.
#pragma once
#include <afxwin.h>
class CSimpleBitmapButton : public CButton
{
DECLARE_DYNAMIC(CSimpleBitmapButton)
protected:
enum EButtonState
{
NORMAL = 0,
PUSHED = 1
};
public:
CSimpleBitmapButton();
BOOL Open( int resource_id );
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
DECLARE_MESSAGE_MAP()
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
protected:
int Width, Height;
BOOL Pushed;
CBitmap Bitmap;
};
Save below as a SimpleBitmapButton.cpp and include it in your project.
#include "stdafx.h"
#include "SimpleBitmapButton.h"
const int BUTTON_IMAGE_NUM = 2;
IMPLEMENT_DYNAMIC(CSimpleBitmapButton, CButton)
BEGIN_MESSAGE_MAP(CSimpleBitmapButton, CButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_CREATE()
END_MESSAGE_MAP()
CSimpleBitmapButton :: CSimpleBitmapButton()
{
Pushed = FALSE;
Width = 0;
Height = 0;
}
void CSimpleBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC memDC;
memDC.CreateCompatibleDC( NULL );
CBitmap *oldBitmap = memDC.SelectObject( &Bitmap );
if( Pushed == FALSE )
BitBlt( lpDrawItemStruct->hDC, 0, 0, Width, Height, memDC, 0, 0, SRCCOPY );
else
BitBlt( lpDrawItemStruct->hDC, 0, 0, Width, Height, memDC, Width , 0, SRCCOPY );
memDC.SelectObject( oldBitmap );
}
BOOL CSimpleBitmapButton :: Open( int resource_id )
{
Pushed = FALSE;
Bitmap.LoadBitmap( resource_id );
//adjust the button size
BITMAP bm;
Bitmap.GetObject(sizeof(BITMAP),&bm);
Width = bm.bmWidth / BUTTON_IMAGE_NUM;
Height = bm.bmHeight;
RECT rect;
GetWindowRect( &rect );
GetParent()->ScreenToClient( &rect );
rect.right = rect.left + Width;
rect.bottom = rect.top + Height;
MoveWindow( &rect );
return TRUE;
}
void CSimpleBitmapButton::OnLButtonDown(UINT nFlags, CPoint point)
{
Pushed = TRUE;
Invalidate( FALSE );
CButton::OnLButtonDown(nFlags, point);
}
void CSimpleBitmapButton::OnLButtonUp(UINT nFlags, CPoint point)
{
Pushed = FALSE;
Invalidate( FALSE );
CButton::OnLButtonUp(nFlags, point);
}
Import this bitmap to resource.
Then set IDB_ROUND_BUTTON for resource ID.
Add button on your dialog and set the "Owner Darw" proerty to True. Important!
Add member variables of the button as m_PlayButton.
At the dialog header, include SimpleBitmapButton.h and change the class of m_PlayButton from CButton to CSimpleBitmapButton.
CSimpleBitmapButton m_Button; // it was CButton m_Button;
At the last, set the bitmap on OnInitDialog()
m_PlayButton.Open( IDB_ROUND_BUTTON );
In Windows, given a handle to an icon (HICON), how do you clone it?
e.g.
HICON CloneIcon(HICON OriginalIcon)
{
ICON clone;
//...
return clone;
}
Use the Win32 API function DuplicateIcon:
HICON CloneIcon(HICON OriginalIcon)
{
return DuplicateIcon(NULL, OriginalIcon); //first parameter is unused
}
Here's the Delphi code to clone an icon.
function CloneIcon(ico: HICON): HICON;
var
info: ICONINFO;
bm: BITMAP;
cx, cy: Integer;
begin
//Get the icon's info (e.g. its bitmap)
GetIconInfo(ico, {var}info);
//Get the bitmap info associated with the icon's color bitmap
GetObject(info.hbmColor, sizeof(bm), #bm);
//Copy the actual icon, now that we know its width and height
Result := CopyImage(ico, IMAGE_ICON, bm.bmWidth, bm.bmHeight, 0);
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
end;
And transcoding to a C/C#-style language in my head:
HICON CloneIcon(HICON ico)
{
ICONINFO info;
//Get the icon's info (e.g. its bitmap)
GetIconInfo(ico, ref info);
//Get the bitmap info associated with the icon's color bitmap
BITMAP bm;
GetObject(info.hbmColor, sizeof(bm), &bm));
//Copy the actual icon, now that we know its width and height
HICON result = CopyImage(ico, IMAGE_ICON, bm.bmWidth, bm.bmHeight, 0);
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
return result;
}
Note: Any code released into public domain. No attribution required.
I'm quite new to OS-X/Cocoa development, and I'm having some trouble with CTDrawLine. I can happily change the stroke of the text using CGContextSetStrokeXXX variants (I can even use patterns) when drawing with kCGTextStroke, but when I set the mode to kCGTextFill, the fill style of the current context is ignored, and the text is rendered black. Here's some code that demonstrates the problem.
-(void) drawRect: (NSRect)rect {
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
float x = 50;
float y = 50;
CTFontRef font = CTFontCreateWithName(CFSTR("Arial"), 74, NULL);
CFStringRef stringRef = CFStringCreateWithCString(NULL, "Hello SO", kCFStringEncodingUTF8);
CFStringRef keys[] = { kCTFontAttributeName };
CFTypeRef values[] = { font };
CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
(const void**)&values, sizeof(keys)/sizeof(keys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, stringRef, attributes);
CTLineRef line = CTLineCreateWithAttributedString(attrString);
CGContextSetTextPosition(context, x, y);
CGContextSetTextDrawingMode(context, kCGTextFill);
// why doesn't this work?
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake(0, 0, 200, 200));
CTLineDraw(line, context);
CFRelease(stringRef);
CFRelease(attributes);
CFRelease(line);
CFRelease(attrString);
CFRelease(font);
}
I expect the text to be red, with a red square beneath it (the text would not show up against this background). Instead I see a red square with black text.
The incredibly detailed documentation for CTDrawLine says:
CTLineDraw
Draws a complete line.
There are no obvious alternative routes to specify the fill style in the reference for CoreText or Quartz. The only way I can get the desired text fill style is by using kCGTextClip and filling a rectangle over the area, which is stupid.
I'm testing on OS-X 10.9 and building with XCode 5, with C++11 language extensions, and this is in a .mm file (although I doubt this would be causing the issue).
What am I missing?
Addendum:
It's probably worth noting my desired end result is to be able to render this text filled with patterns as well as solid colours.
After a bit more fiddling around I found you must add the kCTForegroundColorFromContextAttributeName, https://developer.apple.com/library/ios/documentation/Carbon/Reference/CoreText_StringAttributes_Ref/Reference/reference.html
CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorFromContextAttributeName };
CFTypeRef values[] = { font, kCFBooleanTrue };
I'm trying to add bitmaps to a popup menu.
The problem I have is that I create my bitmaps from ICONs dynamically, and I have problems for 24bit color icons vs 24+alpha (32bit) color icons.
It seems that the bitmaps are only always drawn correctly when they are in 32bpp (including alpha channel).
Here's my (test) code:
void ConvertIconToBitmap(CBitmap& bmpObj, HICON hIcon, int cx, int cy, BOOL useDIB) {
CClientDC screenDC(NULL);
CBitmap bmpTmp;
HANDLE_API_FAILURE( bmpTmp.CreateCompatibleBitmap(&screenDC, cx, cy) );
CDC memDC;
HANDLE_API_FAILURE( memDC.CreateCompatibleDC(&screenDC) );
CBitmap* pOldBmp = memDC.SelectObject(&bmpTmp);
HANDLE_API_FAILURE( ::DrawIconEx( memDC.GetSafeHdc(), 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL) );
memDC.SelectObject( pOldBmp );
HBITMAP hDibBmp = (HBITMAP)::CopyImage((HANDLE)(HBITMAP)bmpTmp, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
HANDLE_API_FAILURE( hDibBmp );
if (useDIB) {
HANDLE_API_FAILURE( bmpObj.Attach(hDibBmp) ); // works for 32bit/transparanecy
} else {
HANDLE_API_FAILURE( bmpObj.Attach(bmpTmp.Detach()) ); // works for 24bit
}
}
...
CMenu menu;
menu.LoadMenu(IDR_POPUPMENU);
CMenu* pMenu = menu.GetSubMenu(0);
int cx, cy;
cx = cy = GetSystemMetrics(SM_CYMENU);
MENUITEMINFO mii;
mii.cbSize = sizeof mii;
mii.fMask = MIIM_BITMAP;
HICON pwdIco = ExtractIcon(NULL/*=current instance*/, L"path/to/file.exe", 0);
// If icon is 32bit-alpha this works, but doesn't work with 24bit icon
CBitmap bmpTop;
ConvertIconToBitmap(bmpTop, pwdIco, cx, cy, TRUE);
mii.hbmpItem = bmpTop;
pMenu->SetMenuItemInfo(ID_MENU_TOP, &mii, FALSE);
// If icon is 32bit-alpha transparent areas are shown in black, but 24bit icon is also displayed correctly
CBitmap bmpApp;
ConvertIconToBitmap(bmpApp, pwdIco, cx, cy, FALSE);
HBITMAP bmpTransp = bmpApp;
mii.hbmpItem = bmpTransp;
pMenu->SetMenuItemInfo(ID_MENU_TEST, &mii, FALSE);
this->ClientToScreen(&point);
pMenu->TrackPopupMenu(nFlags, point.x, point.y, this);
Since I need to dynamically populate the menu entries images from existing file's icons, I can't just statically fiddle out the bitmaps and use these instead of icons.
What are the requirements for the HBITMAP passed in the hbmpItem member of the MENUITEMINFO structure passed to SetMenuItemInfo ???
And how do I make sure the bitmap "created" with DrawIconEx does fulfill these requirements?
Oh, and to my great pleasure I just learned that 32-bit alpha-blended menu item bitmaps don't work at under Windows XP (transparent=black there), so I'll have to map transparency myself somehow it seems. (Possibly by replacing some color with GetSysColor(COLOR_MENU).)