2021년 7월 20일 화요일

WPF WindowChrome Window Maximized 했을때 화면 잘림 현상 해결

 Window 에 아래 코드 입력


     
     private void Window_Loaded(object sender, RoutedEventArgs e)
     {
       IntPtr handle = (new WindowInteropHelper(this)).Handle;
       HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc));
     }

     private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)  
     {  
       switch (msg)  
       {  
         case 0x10:  
           //Console.WriteLine("Close reason: Clicking X");  
           break;  
         case 0x11:  
         case 0x16:  
           //Console.WriteLine("Close reason: WindowsShutDown");  
           break;  
         case 0x0024:  
           WmGetMinMaxInfo(hwnd, lParam);  
           handled = true;  
           break;  
         case 0x0046:  
           NativeMethods.WINDOWPOS pos = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS));  
           if ((pos.flags & (int)(NativeMethods.SWP.NOMOVE)) != 0)  
           {  
             return IntPtr.Zero;  
           }  
   
           Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;  
           if (wnd == null)  
           {  
             return IntPtr.Zero;  
           }  
   
           bool changedPos = false;  
           if (pos.cx < wnd.MinWidth) { pos.cx = (int)wnd.MinWidth; changedPos = true; }  
           if (pos.cy < wnd.MinHeight) { pos.cy = (int)wnd.MinHeight; changedPos = true; }  
           if (!changedPos)  
           {  
             return IntPtr.Zero;  
           }  
   
           Marshal.StructureToPtr(pos, lParam, true);  
           handled = true;  
           break;  
         case 0x112:  
           if (((ushort)wParam & 0xfff0) == 0xf060)  
           {  
             // close (alt + F4)  
             handled = true;  
           }  
           break;  
         default:  
           break;  
       }  
       return IntPtr.Zero;  
     }  
   
     private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)  
     {  
       NativeMethods.MINMAXINFO mmi = (NativeMethods.MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(NativeMethods.MINMAXINFO));  
   
       // Adjust the maximized size and position to fit the work area of the correct monitor  
       int MONITOR_DEFAULTTONEAREST = 0x00000002;  
       IntPtr monitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);  
   
       if (monitor != System.IntPtr.Zero)  
       {  
         NativeMethods.MONITORINFO monitorInfo = new NativeMethods.MONITORINFO();  
         NativeMethods.GetMonitorInfo(monitor, monitorInfo);  
         NativeMethods.RECT rcWorkArea = monitorInfo.rcWork;  
         NativeMethods.RECT rcMonitorArea = monitorInfo.rcMonitor;  
         mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);  
         mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);  
         mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);  
         mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);  
       }  
       Marshal.StructureToPtr(mmi, lParam, true);  
     }  

 public class NativeMethods  
   {  
     [DllImport("user32.dll", CharSet = CharSet.Auto)]  
     internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);  
   
     // Define the Win32 API methods we are going to use  
     [DllImport("user32.dll")]  
     internal static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);  
   
     [DllImport("user32.dll", CharSet = CharSet.Unicode)]  
     internal static extern bool InsertMenu(IntPtr hMenu, uint wPosition, uint wFlags, UIntPtr wIDNewItem, string lpNewItem);  
   
     [DllImport("user32.dll", CharSet = CharSet.Unicode)]  
     internal static extern int ModifyMenu(IntPtr hMenu, uint uPosition, uint wFlags, UIntPtr wIDNewItem, string text);  
   
     [DllImport("user32.dll")]  
     internal static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);  
   
     [DllImport("user32")]  
     public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);  
   
     [DllImport("User32")]  
     public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);  
   
     #region Win32 Imports  
     internal const UInt32 MF_BYCOMMAND = 0x00000000;  
   
     internal const UInt32 SC_SIZE = 0xF000;  
     internal const UInt32 SC_MOVE = 0xF010;  
     internal const UInt32 SC_MINIMIZE = 0xF020;  
     internal const UInt32 SC_MAXIMIZE = 0xF030;  
     internal const UInt32 SC_NEXTWINDOW = 0xF040;  
     internal const UInt32 SC_PREVWINDOW = 0xF050;  
     internal const UInt32 SC_CLOSE = 0xF060;  
     internal const UInt32 SC_VSCROLL = 0xF070;  
     internal const UInt32 SC_HSCROLL = 0xF080;  
     internal const UInt32 SC_MOUSEMENU = 0xF090;  
     internal const UInt32 SC_KEYMENU = 0xF100;  
     internal const UInt32 SC_ARRANGE = 0xF110;  
     internal const UInt32 SC_RESTORE = 0xF120;  
     internal const UInt32 SC_TASKLIST = 0xF130;  
     internal const UInt32 SC_SCREENSAVE = 0xF140;  
     internal const UInt32 SC_HOTKEY = 0xF150;  
     internal const UInt32 SC_DEFAULT = 0xF160;  
     internal const UInt32 SC_MONITORPOWER = 0xF170;  
     internal const UInt32 SC_CONTEXTHELP = 0xF180;  
     internal const UInt32 SC_SEPARATOR = 0xF00F;  
   
     /// Define our Constants we will use  
     public const Int32 WM_SYSCOMMAND = 0x112;  
     public const Int32 MF_SEPARATOR = 0x800;  
     public const Int32 MF_BYPOSITION = 0x400;  
     public const Int32 MF_STRING = 0x0;  
   
     public enum SWP : uint  
     {  
       NOSIZE = 0x0001,  
       NOMOVE = 0x0002,  
       NOZORDER = 0x0004,  
       NOREDRAW = 0x0008,  
       NOACTIVATE = 0x0010,  
       FRAMECHANGED = 0x0020,  
       SHOWWINDOW = 0x0040,  
       HIDEWINDOW = 0x0080,  
       NOCOPYBITS = 0x0100,  
       NOOWNERZORDER = 0x0200,  
       NOSENDCHANGING = 0x0400,  
     }  
   
     /// <summary>  
     /// POINT aka POINTAPI  
     /// </summary>  
     [StructLayout(LayoutKind.Sequential)]  
     public struct POINT  
     {  
       /// <summary>  
       /// x coordinate of point.  
       /// </summary>  
       public int x;  
       /// <summary>  
       /// y coordinate of point.  
       /// </summary>  
       public int y;  
   
       /// <summary>  
       /// Construct a point of coordinates (x,y).  
       /// </summary>  
       public POINT(int x, int y)  
       {  
         this.x = x;  
         this.y = y;  
       }  
     }  
   
     [StructLayout(LayoutKind.Sequential)]  
     public struct MINMAXINFO  
     {  
       public POINT ptReserved;  
       public POINT ptMaxSize;  
       public POINT ptMaxPosition;  
       public POINT ptMinTrackSize;  
       public POINT ptMaxTrackSize;  
     };  
   
     /// <summary>  
     /// </summary>  
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]  
     public class MONITORINFO  
     {  
       /// <summary>  
       /// </summary>        
       public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));  
   
       /// <summary>  
       /// </summary>        
       public RECT rcMonitor = new RECT();  
   
       /// <summary>  
       /// </summary>        
       public RECT rcWork = new RECT();  
   
       /// <summary>  
       /// </summary>        
       public int dwFlags = 0;  
     }  
   
     [StructLayout(LayoutKind.Sequential)]  
     public struct WINDOWPOS  
     {  
       public IntPtr hwnd;  
       public IntPtr hwndInsertAfter;  
       public int x;  
       public int y;  
       public int cx;  
       public int cy;  
       public int flags;  
     }  
   
     /// <summary> Win32 </summary>  
     [StructLayout(LayoutKind.Sequential, Pack = 0)]  
     public struct RECT  
     {  
       /// <summary> Win32 </summary>  
       public int left;  
       /// <summary> Win32 </summary>  
       public int top;  
       /// <summary> Win32 </summary>  
       public int right;  
       /// <summary> Win32 </summary>  
       public int bottom;  
   
       /// <summary> Win32 </summary>  
       public static readonly RECT Empty = new RECT();  
   
       /// <summary> Win32 </summary>  
       public int Width  
       {  
         get { return Math.Abs(right - left); } // Abs needed for BIDI OS  
       }  
       /// <summary> Win32 </summary>  
       public int Height  
       {  
         get { return bottom - top; }  
       }  
   
       /// <summary> Win32 </summary>  
       public RECT(int left, int top, int right, int bottom)  
       {  
         this.left = left;  
         this.top = top;  
         this.right = right;  
         this.bottom = bottom;  
       }  
   
   
       /// <summary> Win32 </summary>  
       public RECT(RECT rcSrc)  
       {  
         this.left = rcSrc.left;  
         this.top = rcSrc.top;  
         this.right = rcSrc.right;  
         this.bottom = rcSrc.bottom;  
       }  
   
       /// <summary> Win32 </summary>  
       public bool IsEmpty  
       {  
         get  
         {  
           // BUGBUG : On Bidi OS (hebrew arabic) left > right  
           return left >= right || top >= bottom;  
         }  
       }  
       /// <summary> Return a user friendly representation of this struct </summary>  
       public override string ToString()  
       {  
         if (this == RECT.Empty) { return "RECT {Empty}"; }  
         return "RECT { left : " + left + " / top : " + top + " / right : " + right + " / bottom : " + bottom + " }";  
       }  
   
       /// <summary> Determine if 2 RECT are equal (deep compare) </summary>  
       public override bool Equals(object obj)  
       {  
         if (!(obj is Rect)) { return false; }  
         return (this == (RECT)obj);  
       }  
   
       /// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary>  
       public override int GetHashCode()  
       {  
         return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();  
       }  
   
   
       /// <summary> Determine if 2 RECT are equal (deep compare)</summary>  
       public static bool operator ==(RECT rect1, RECT rect2)  
       {  
         return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom);  
       }  
   
       /// <summary> Determine if 2 RECT are different(deep compare)</summary>  
       public static bool operator !=(RECT rect1, RECT rect2)  
       {  
         return !(rect1 == rect2);  
       }  
     }  
     #endregion  
   }  



2021년 7월 15일 목요일

c# convert short/int value to byte array in bigendian

short val = 0x1234;

sendData[0] = (byte)(val >> 8);

sendData[1] = (byte)val;


int val2 = 0x12345678;

sendData[0] = (byte)(val2 >> 24);

sendData[1] = (byte)(val2 >> 16);

sendData[2] = (byte)(val2 >> 8);

sendData[3] = (byte)val2;

2021년 6월 24일 목요일

C# 라디오버튼/체크박스 이미지 버튼 처리

 1. Resources.resx 를 열어서 "리소스 추가"->"기존 파일 추가" 해서 .png/.jpg 등 이미지 파일을 추가한다.

예) check.png, uncheck.png


2. 디자이너에서 라디오버튼 or 체크박스 속성중 

Appearance->Button 선택

AutoSize False 선택

BackgroundImage 클릭해서 1번에서 추가한 이미지 선택(프로젝트 리소스 파일)

BackgroundImageLayout 원하는 속성선택

FlatAppearance->BorderSize 0 입력

FlatAppearance->CheckedBackColor = Transparent 입력

FlatAppearance->MouseDownBackColor = Transparent 입력

FlatAppearance->MouseOverBackColor = Transparent 입력

FlatStyle->Flat 선택

Size->이미지 사이즈 입력


3. 버튼 이벤트 CheckedChanged 핸들러 메소드에서 버튼 이미지 변환 코드 입력

private void checkButton_CheckedChanged(object sender, EventArgs e)

{

    if (checkButton.Checked)

    {

        checkButton.BackgroundImage = Properties.Resources.check;

    }

    else

    {

        checkButton.BackgroundImage = Properties.Resources.uncheck;

    }

}


2021년 6월 14일 월요일

Qt QString section 함수를 활용한 path 체크 함수

경로 문자열을 입력하면 해당 경로를 자동 체크해서 없으면 경로생성해주는 함수

void checkPath(QString path)
{
    int i = 0;
    QString filepath = "";

    do
    {
        filepath = path.section('/', 0, i++);   // 섹션별 분할

        // 디렉토리 존재 여부 체크  없으면 생성
        QDir dir(filepath);
        if (!dir.exists()) {
            dir.mkdir(filepath);
        }

    } while (filepath != path);
}


checkPath("d:/aaa/bbb/ccc"); => 해당 경로에 디렉토리 없으면 각 디렉토리 자동생성

2021년 4월 30일 금요일

C# 멀티캐스트 소켓 생성

 protected Socket socket;   
 ...  

 void CreateMulticastSocket(string multicastIP, int port, bool exclusive)     
 {  
   sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);  
   
   socket.Blocking = false;  
   socket.ExclusiveAddressUse = exclusive;  
      
   if (!exclusive) socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);  
      
   IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);  
   socket.Bind(endpoint);  
    
   IPAddress ip = IPAddress.Parse(multicastIP);  
   socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));          
 }  

2021년 4월 8일 목요일

C# 시리얼 통신 데이터 파싱

시리얼 통신 데이터는 TCP와 유사하게 전송되는 바이트 길이만큼 수신되지 않는다. 

만약 송신자->수신자 에게 주기적으로 20 바이트를 전송한다고 했을때 수신측에서 시리얼 통신 데이터를 read 했을때 정확하게 20 바이트를 수신하지 않고 5+15 와 같이 잘려서 수신될 수 있다는 말이다. 
연속해서 데이터를 수신할때는 더욱 다양한 상황이 발생할 수 있다. 20, 20 바이트를 연속해서 보냈을때 25+15로 받을 수도 있고 1+15+15+9 와 같이 받을 수도 있다. 

이런 모든 경우의 수에 대해 올바르게 처리하려면 전송되는 데이터 단위가 고정길이(20 바이트)라고 가정했을때 수신 버퍼를 크게 할당한 다음 20 바이트씩 끊어서 처리해야 한다. 간단한 소스는 다음과 같다.

 
         private SerialPort serial = new SerialPort();  
         private byte[] serialRecvBuffer = new byte[1024];    // 수신버퍼  
         private int serialRecvBufferIndex = 0;    // 수신버퍼 인덱스 - 현재까지 수신한 데이터 길이와 같음  
         ...  
           
         serial.DataReceived += Serial_DataReceived;  
         ...  
           
         private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)  
         {  
             try  
             {  
                 // 시리얼 데이터 수신  
                 int size = serial.BytesToRead;  
                 byte[] bytesRead = new byte[size];  
   
                 int ret = serial.Read(bytesRead, 0, size);  
   
                 // 수신버퍼에 복사  
                 Buffer.BlockCopy(bytesRead, 0, serialRecvBuffer, serialRecvBufferIndex, size);  
                 serialRecvBufferIndex += size;  
               
                 while (serialRecvBufferIndex >= 20)    // 수신버퍼 크기가 20보다 크거나 같으면 데이터 처리  
                 {  
                     ProcessSerialData();    // 데이터 처리  
   
                     // 데이터 처리 후 뒤에 남은 데이터들 앞으로 복사  
                     Buffer.BlockCopy(serialRecvBuffer, 20, serialRecvBuffer, 0, serialRecvBufferIndex - 20);  
                     serialRecvBufferIndex -= 20;  
                 }  
             }  
             catch (Exception ex)  
             {  
                 Console.WriteLine(ex.ToString());  
                 serialRecvBufferIndex = 0;  
             }  
         }  

2021년 1월 12일 화요일

ffmpeg common.h 에서 C1060 compiler is out of heap space 에러 처리

 libavutil/common.h 제일 위에 아래 코드 추가해준다


#ifndef AVUTIL_COMMON_H
#define AVUTIL_COMMON_H

#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
#define INT64_MAX    _I64_MAX 
#define INT64_MIN    ((int64_t)_I64_MIN)