【发布时间】:2021-02-26 03:02:52
【问题描述】:
我有一个动画 GIF,我正在尝试显示它,但我无法让它工作。它不会运行并在SetTimer(hWnd, ID_TIMER, ((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10, (TIMERPROC)NULL); 行抛出异常0xC0000005: Access violation reading location 0x80000B00.。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
Image* m_pImage = new Image(L"spinner.gif");
UINT m_iCurrentFrame = 0;
UINT m_FrameCount = 0;
PropertyItem* m_pItem = 0;
switch(message) {
...
case WM_TIMER: {
//Because there will be a new delay value
KillTimer(hWnd, ID_TIMER);
//Change Active frame
GUID Guid = FrameDimensionTime;
m_pImage->SelectActiveFrame(&Guid, m_iCurrentFrame);
//New timer
SetTimer(hWnd, ID_TIMER, ((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10, NULL);
//Again move to the next
m_iCurrentFrame = (++m_iCurrentFrame) % m_FrameCount;
InvalidateRect(hWnd, NULL, FALSE);
break;
}
case WM_PAINT:{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
Graphics graphics(hdc);
//First of all we should get the number of frame dimensions
//Images considered by GDI+ as:
//frames[animation_frame_index][how_many_animation];
UINT count = m_pImage->GetFrameDimensionsCount();
//Now we should get the identifiers for the frame dimensions
GUID* m_pDimensionIDs = new GUID[count];
m_pImage->GetFrameDimensionsList(m_pDimensionIDs, count);
//For gif image , we only care about animation set#0
WCHAR strGuid[40];
StringFromGUID2(m_pDimensionIDs[0], strGuid, 40);
m_FrameCount = m_pImage->GetFrameCount(&m_pDimensionIDs[0]);
//PropertyTagFrameDelay is a pre-defined identifier
//to present frame-delays by GDI+
UINT TotalBuffer = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay);
m_pItem = (PropertyItem*)malloc(TotalBuffer);
m_pImage->GetPropertyItem(PropertyTagFrameDelay, TotalBuffer, m_pItem);
//Set Current Frame at #0
m_iCurrentFrame = 0;
GUID Guid = FrameDimensionTime;
m_pImage->SelectActiveFrame(&Guid, m_iCurrentFrame);
//Use Timer
//NOTE HERE: frame-delay values should be multiply by 10
SetTimer(hWnd, ID_TIMER, ((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10, (TIMERPROC)NULL);
//Move to the next frame
++m_iCurrentFrame;
InvalidateRect(hWnd, NULL, FALSE);
//Finally simply draw
graphics.DrawImage(m_pImage, 120, 120, 100, 100);
EndPaint(hWnd, &ps);
break;
}
...
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
我发现的大部分例子是 WCF 或者函数被贬值了。
【问题讨论】:
-
可能是因为您在
WinProc中一遍又一遍地加载 gif,而且您从未删除过指针,因此造成了巨大的内存泄漏。 -
PropertyItem* m_pItem = 0;然后SetTimer(hWnd, ID_TIMER, ((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10, NULL);你正在使用空指针。 -
您正在解除对无效指针的引用,导致尝试读取地址
0x80000B00的内存。调试器将为您提供了解正在发生的事情所需的所有详细信息。假设基本熟悉 C。 -
现在出现
0xC0000005: Access violation reading location 0x880027EB.的错误。 -
可能和公式
((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10有关。
标签: c++ winapi visual-studio-2019 gdi+