my question is related to aritcle link:
http://www.codeproject.com/Articles/3274/Drawing-Arrows
I did:
a.nWidth = 10;
a.fTheta = 0.3f;
a.bFill = true;
Canvas->MoveTo(100, 100);
HDC hDC = GetDC(Canvas->Handle);
ArrowTo(hDC, 200, 100, &a);
And I got linker error:"Unresolved external 'ArrowTo(void *, int, int, tARROWSTRUCT *)' referenced"
Any ideas?
Related
I'm using some C code to take a screenshot of a window, translated directly from a PowerBuilder sample that works perfectly. Here's the part up to where there's a problem:
extern "C" __declspec(dllexport) BOOL __stdcall WindowScreenShot(const wchar_t* fileName, unsigned long x, unsigned long y,
unsigned long width, unsigned long height)
{
HWND ll_hWnd;
HDC ll_hdc, ll_hdcMem;
HBITMAP ll_hBitmap;
HANDLE hDib = NULL, hFile = NULL;
char* lpBitmap = NULL;
BOOL lb_result, lb_ok = FALSE;
BITMAPINFO lstr_Info;
BITMAPFILEHEADER lstr_Header;
int li_pixels;
DWORD dwBmpSize, dwBytesWritten;
// get handle to windows background
ll_hWnd = GetDesktopWindow();
// Get the device context of window and allocate memory
ll_hdc = GetDC(ll_hWnd);
ll_hdcMem = CreateCompatibleDC(ll_hdc);
ll_hBitmap = CreateCompatibleBitmap(ll_hdc, width, height);
if (ll_hBitmap != 0)
{
// Select an object into the specified device context
SelectObject(ll_hdcMem, ll_hBitmap);
// Copy the bitmap from the source to the destination
lb_result = BitBlt(ll_hdcMem, 0, 0, width, height, ll_hdc, x, y, SRCCOPY);
lstr_Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Get the bitmapinfo (THIS LINE IS FAILING CURRENTLY)
if (GetDIBits(ll_hdcMem, ll_hBitmap, 0, height, NULL, &lstr_Info, DIB_RGB_COLORS) > 0)
{ ...
That last call to GetDIBits always fails with the only documented error that it can give, ERROR_INVALID_PARAMETER. Since this code is basically absolutely identical to the PowerBuilder code, in terms of the structures used and Windows APIs called, I just have no idea how to resolve it. I've also read the API docs carefully and it all looks like it should work.
Any bright ideas? Thanks.
Paul Ogilvie's answer resolved it - I was using uninitialized structures because they were automatic variables. As soon as I fixed that the code worked.
I've been trying to make a simple window using WinAPI, it compiles and links with some warnings, when I open the program the window shows up, but when I try to interact with it, a windows warning sound is played and it doesn't allow me to use the window, not even close it, I have to use task manager.
To compile it I'm using Microsoft's "cl.exe" with the command line:
cl /c window.c
and the warnings are:
window.c(39): warning C4133: 'function': incompatible types, from 'LPSTR' to 'HINSTANCE'
window.c(40): warning C4133: 'function': incompatible types, from 'LPSTR' to 'HINSTANCE'
window.c(41): warning C4047: '=': 'HBRUSH' differs in levels of indirection from 'int'
To link I use crinkler with the commandline:
crinkler /NODEFAULTLIB /ENTRY:main /SUSBYSTEM:WINDOWS /TINYHEADER /TINYIMPORT /OUT:c.exe window.obj kernel32.lib user32.lib
and the warning is:
: warning LNK: Entry point not at start of section, jump necessary
The code I'm using is:
#include <windows.h>
#define WINDOW_STYLE WS_VISIBLE+WS_OVERLAPPEDWINDOW-WS_THICKFRAME-WS_MAXIMIZE
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
static const char* window_name = "My Window";
RECT window_rect = {0, 0, WINDOW_HEIGHT, WINDOW_WIDTH};
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
int main()
{
int ret = 0;
HMODULE instance = GetModuleHandleA(NULL);
AdjustWindowRect(&window_rect, WINDOW_STYLE, FALSE);
WNDCLASSEXA window_class;
window_class.cbSize = 48;
window_class.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
window_class.lpfnWndProc = WindowProc;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = instance;
window_class.hIcon = LoadIconA(IDI_APPLICATION, 0);
window_class.hCursor = LoadCursorA(IDI_APPLICATION, 0);
window_class.hbrBackground = COLOR_WINDOW;
window_class.lpszMenuName = 0;
window_class.lpszClassName = window_name;
window_class.hIconSm = 0;
if (RegisterClassExA(&window_class)) {
HWND window = CreateWindowExA(
0,
window_name,
window_name,
WINDOW_STYLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
0,
0,
instance,
NULL);
ShowWindow(window, SW_SHOW);
UpdateWindow(window);
MSG msg;
while(1)
{
if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
ExitProcess(0);
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
} else {
ret = 1;
}
ExitProcess(0);
return ret;
}
Does anybody know how to fix it? Thanks.
The following line doesn't do what you think it does:
#define WINDOW_STYLE WS_VISIBLE+WS_OVERLAPPEDWINDOW-WS_THICKFRAME-WS_MAXIMIZE
While somewhat common, and occasionally even producing the correct value, it is a very brittle way to implement bit manipulations. In this particular case, the expression expands to:
0x10000000L + 0x00CF0000L - 0x00040000L - 0x01000000L
This produces the value 0xFFCB0000L1 (due to accidentally using WS_MAXIMIZE instead of WS_MAXIMIZEBOX). This translates to a window with the following styles:
WS_POPUP
WS_CHILD (note, that this is already mutually exclusive with WS_POPUP)
WS_ICONIC
WS_VISIBLE
WS_DISABLED
...
As documented:
WS_DISABLED: The window is initially disabled. A disabled window cannot receive input from the user. To change this after a window has been created, use the EnableWindow function.
That explains why you cannot interact with your window. The fix is simple: Use bitwise operators for bit manipulations instead of arithmetic operators:
#define WINDOW_STYLE (WS_VISIBLE | WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZE)
1 Leaving the fact, that the behavior for signed overflow is undefined aside.
I am trying to create an HBITMAP from an array which will contain the color values for the Pixels. The thing is when I try to create a 24-bpp Bitmap, the CreateDIBItmap is using BGR values instead of RGB as I would like.
The code to create the Bitmap is as follows:
image_size = 600 * 600 * 3;
aimp_buffer = (char *)malloc(image_size * sizeof(char));
for (counter = 0; counter < image_size;)
{
aimp_buffer[counter++] = 255;
aimp_buffer[counter++] = 0;
aimp_buffer[counter++] = 0;
}
ads_scrbuf->avo_buffer = (void *)aimp_buffer;
ads_scrbuf->im_height = 600;
ads_scrbuf->im_width = 600;
ads_scrbuf->im_scanline = 600;
memset(&info, 0, sizeof(info));
memset(&info.bmiHeader, 0, sizeof(info.bmiHeader));
info.bmiHeader.biBitCount = 24;
info.bmiHeader.biHeight= -600;
info.bmiHeader.biWidth= 600;
info.bmiHeader.biSize = sizeof(info.bmiHeader);
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biCompression = BI_RGB;
memset(&header, 0, sizeof(BITMAPV5HEADER));
header.bV5Width = 600;
header.bV5Height = 600;
header.bV5BitCount = 24;
header.bV5Size = sizeof(BITMAPV5HEADER);
header.bV5Planes = 1;
header.bV5Compression = BI_RGB;
*adsp_hBitmap = CreateDIBitmap(GetDC(ds_apiwindow), (BITMAPINFOHEADER *)&header,
CBM_INIT, (void *)ads_scrbuf->avo_buffer, &info, DIB_RGB_COLORS)
This should create a Red background for all of the image, but instead it is blue.
The Windows convention for DIB bitmaps is BGR. You can't change that. You will simply have to adapt to it.
If you load for instance *.bmp file to memory or rather you make a variable lets say DWORD cRef = 0xFF0000 and fill a memory with it, in second case you will see RED color, so the byte order is BGR in both cases (seen as 0xRRGGBB value in source code editor for mentioned variable). But! Try to call e.g. SetTextColor(hDc, cRef) or so. The very same value will be BLUE, so it will be a hell of an adaptation, because Windows convention for DIB bitmaps is just the opposite of Windows convention for e.g. HBRUSH objects. I'd really wonder in which way is this useful..
I am attempting to use GDI+ in my C application to take a screenshot and save it as JPEG. I am using GDI+ to convert the BMP to JPEG but apparently when calling the GdiplusStartup function, the return code is 2(invalid parameter) instead of 0:
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
//if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != 0)
// printf("GDI NOT WORKING\n");
printf("%d",GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL));
HDC hdc = GetDC(NULL); // get the desktop device context
HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself
// get the height and width of the screen
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
// create a bitmap
HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);
// use the previously created device context with the bitmap
SelectObject(hDest, hbDesktop);
// copy from the desktop device context to the bitmap device context
// call this once per 'frame'
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);
// after the recording is done, release the desktop context you got..
ReleaseDC(NULL, hdc);
// ..and delete the context you created
DeleteDC(hDest);
SaveJpeg(hbDesktop,"a.jpeg",100);
GdiplusShutdown(gdiplusToken);
return 0;
}
I am trying to figure out why the GdiplusStartup function is not working.
Any thoughts?
Initialize gdiplusStartupInput variable with the following values: GdiplusVersion = 1, DebugEventCallback = NULL, SuppressBackgroundThread = FALSE, SuppressExternalCodecs = FALSE
According to MSDN article GdiplusStartup function http://msdn.microsoft.com/en-us/library/windows/desktop/ms534077%28v=vs.85%29.aspx
GdiplusStartupInput structure has default constructor which initializes the structure with these values. Since you call the function from C, constructor is not working and structure remains uninitialized. Provide your own initialization code to solve the problem.
// As Global
ULONG_PTR gdiplusToken;
// In top of main
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&programInfo.gdiplusToken, &gdiplusStartupInput, NULL);
works for me.
I'm trying to take a screenshot of the entire screen with C and GTK. I don't want to make a call to an external application for speed reasons. I've found Python code for this (Take a screenshot via a python script. [Linux]); I just need to figure out how to do that in C.
After looking at the GNOME-Screenshot code and a Python example, I came up with this:
GdkPixbuf * get_screenshot(){
GdkPixbuf *screenshot;
GdkWindow *root_window;
gint x_orig, y_orig;
gint width, height;
root_window = gdk_get_default_root_window ();
gdk_drawable_get_size (root_window, &width, &height);
gdk_window_get_origin (root_window, &x_orig, &y_orig);
screenshot = gdk_pixbuf_get_from_drawable (NULL, root_window, NULL,
x_orig, y_orig, 0, 0, width, height);
return screenshot;
}
Which seems to work perfectly. Thanks!
9 years passed and as mentioned above API is removed.
As far as I understand, currently the bare minimum to do this at Linux is:
GdkWindow * root;
GdkPixbuf * screenshot;
gint x, y, width, height;
root = gdk_get_default_root_window ();
gdk_window_get_geometry (root, &x, &y, &width, &height);
screenshot = gdk_pixbuf_get_from_window (root, x, y, width, height);
// gdk_pixbuf_save...
This is very slightly tested and may fail. Further reading is in gnome-screenshooter repo